I am reading source at openssl, and the following lines apparently defines SSL_OP_NO_SSLv3 if it is not defined yet. Never saw such magic before. Can anyone teach me the syntax here?
#if !defined(OPENSSL_NO_SSL3)
| SSL_OP_NO_SSLv3
#endif
You can reference this link for full file and see line 327.
The question makes sense only with the surrounding code (slightly simplified here):
mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
#if !defined(OPENSSL_NO_SSL3)
|SSL_OP_NO_SSLv3
#endif
;
The preprocessor just does textual substitution. So if the preprocessor macro OPENSSL_NO_SSL3 is not defined, the preprocessed code will look like this:
mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
|SSL_OP_NO_SSLv3
;
otherwise the preprocessed code ill look like this:
mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
;
It doesn't define a macro. It adds an expression to a bitmask. That operation there is bitwise or. The macro/enum SSL_OP_NO_SSLv3 must exist for it to be valid code.
If the macro OPENSSL_NO_SSL3 is defined, then the code inside the conditional isn't included in the source.
Having the preprocessor check for macro definitions is a common way to implement conditional compilation. This way the same source can be compiled under various configurations. The macros to check against can be defined in source with #define, passed by the build system (like with the gcc -D option), or be builtin to the preprocessor (such as __STDC_IEC_559__).
Related
I take a project which written in c, and there are lots of Macros.
I want to use a new macro to check if the macro is activated or not.
But the symbol # is reserved in macro. How to fix my code? Thanks :)
#define CHECK_MACRO( macro )\
#ifdef macro
printf("defined "#macro"\n");\
#else
printf("not defined "#macro"\n");\
#endif
You cannot use preprocessor conditional directives inside a macro. Generally speaking, the solution is to turn that inside out: use conditional directives to define the macro differently in different cases. That will not work for a generic macro-test macro such as you propose, however, and it also is limited by the fact that it determines whether the condition holds at the point where the macro is defined, not the point where it is used.
You may perhaps take consolation in the fact that this was never going to work anyway, as a result of the fact the arguments to a function-like macro are expanded before being substituted into the macro's replacement text (except in a couple of special cases that don't apply to the key part of your code).
There are alternatives that could work if the possible values of all macros of interest are limited to short lists of tokens that may appear as or in identifiers. There different alternatives that might be adequate if you can choose a small subset of macros that you're interested in testing. There are no alternatives that do what you propose in its full generality, unless you count writing the conditional compilation directives directly, without a macro, which in fact is the usual way of going about it.
Side note - m4 preprocssor - history/legacy.
In the early days of Unix, the 'm4' processor was used for code generation. It has enhanced features of cpp (or may be cpp is a scaled down version of m4). Specially, it has better support for multi-line macros. It continue to be used in various packages.
Worth mentioning that adding a code generation to your code will make it more complex to maintain/debug.
For example: a.m4
define(`CHECK_MACRO', `
#ifdef $1
printf ("defined #$1\n") ;
#else
printf ("undef #$1\n") ;
#endif
')
#include <stdio.h>
void main(void)
{
CHECK_MACRO(FOO) ;
CHECK_MACRO(BAR) ;
}
Then build/run
m4 a.m4 > a.c
cc a.c
./a.out
undef #FOO
undef #BAR
cc a.c -DFOO
./a.out
defined #FOO
undef #BAR
Usually, the generation was integrated into Makefile with a rule
%.c: %.m4:
m4 -s $< > $#
The -s help track source code line number (it will compile error line number matching the a.m4 source file.
Is it mandatory to write #include at the top of the program and outside the main function?
I tried using #define preprocessor inside the main function and it worked fine with only one exception..that being the constant which i defined using the define directive can be used only after the line #define
For instance say printf("%d",PI); #define PI 3.14will give error "Undefined symbol PI". But in the following code i did not encounter any error
#define PI 3.14
printf("%d",PI);
Is this because C is a procedural language and procedural languages implements top down approach?
Also i would like to know that can we use only #define inside the main function or other preprocessor directives too? If we can use then which ones?
Or is it the other way around, instead of #include we can use all the preprocessor directives in the main function?
The only place you can't put a preprocessor directive is in a macro expansion. The sole exception is #pragma, which can also be written _Pragma().
This has nothing to do with "procedural", but due to the fact that C is defined in terms of 8 translation phases, each of which is "as-if" fully-completed before the next phase. For more details, see the C11 standard, section 5.1.1.2.
One example of when it is useful to use preprocessor directives after the start of a file is for the "X Macro" technique (which many people only know as "those .def files").
Preprocessor directives work pretty much anywhere. Of course, you can make your code confusing pretty easily if you abuse this.
The pre-processor does its work before the compiler performs the source code translation into object code. Pre-processing is mostly a string replacement task, so it can be placed just about anywhere in your code. Of course, if the resulting expansion is syntactically incorrect, the expanded source code will fail to compile.
A commonly tolerated practice is to embed conditional compilation directives inside a function to allow the function to use platform specific APIs.
void some_wrapper_function () {
#if defined(UNIX)
some_unix_specific_function();
#elif defined(WIN32)
some_win32_specific_function();
#else
#error "Compiled on an unsupported platform"
#endif
}
By their nature, the directives themselves normally have to be defined at the beginning of the line, and not somewhere in the middle of source line. But, defined macros can of course appear anywhere in the source, and will be replaced according to the substitution rules defined by your directives.
The trick here is to realize that # directives have traditionally been interpreted by a pre-processor, that runs before any compilation. The pre-processor would produce a new source file, which was then compiled. I don't think any modern compiler works that way by default, but the same principles apply.
So when you say
#include "foo.h"
you're saying "insert the entire contents of foo.h into my source code starting at this line."
You can use this directive pretty much anywhere in a source file, but it's rarely useful (and not often readable) to use it anywhere other than at the start of the source.
I am trying to understand the idea of function like Macros however there are a few points that befuddle me. For example say we have:
#define Max(a,b) ((a)>(b)) ? (a):(b))
and I call it like such
int i = Max(4,5);
This will evaluate a conditional expression equivalent to a>b? If yes then a, else b. But I'm confused as to how the Max function knows what to do with the arguments. Unlike an actual function, the implementation isn't written in code in the calling program. is the statement to the right of the define statement doing this for me? Its just a new thing for me and I want to make sure I understand what is happening here.
This particular part of function like macros confuses me. I know that these types of macros are useful for reducing overhead costs since they exclude the JSR RTS processor instructions which saves memory on the stack.
#define Max(a,b) ((a)>(b)) ? (a):(b))
is a macro, that causes nothing else but a simple textual replacement within your code, which means that during the preprocessing this line:
int i = Max(4,5);
is changed into:
int i = ((4)>(5)) ? (4):(5));
Note that there is no type safety while working with macros like this one and you will have really hard time while debugging your code as well. Good rule of thumb is: Don't use macro when you can achieve the same with function:
int max(int a, int b) {
return (a > b) ? a : b;
}
What the compiler actually sees, after preprocessing, is:
int i = ((4)>(5)) ? (4):(5));
The parameters passed to the macro are substituted into the body of the macro.
Just stop thinking about macro like compilable code. Macros are "resolved" by pre-processor, not actually during compilation stage. So by macro definitions you just define how to process certain string in text file. Only output of pre-processor is passed to compiler. You can use gcc -E to see your source after pre-processor. It is still C code on this stage but without any preprocessor directive.
Hope this will help you.
try to build your code with the gcc -E and see how your code look before compiling it
In fact in the build process the compilator transform your actual code to a preprocessor code.
In the preprocessor phase the compilator replace all macro in your c code with its content and generate another code called preprocessor code and then the compilateor generate the object code from the preprocessor code
The gcc -E allow you to see your preprocessor code
I added this in my code:
#ifdef DEBUG_MODE
printf("i=%d\n",i);
fflush(stdout);
#endif
and my question is, if I'm not in DEBUG_MODE what the compiler does when compiling this?
The compiler will do nothing, because there will be nothing there when DEBUG_MODE is not defined.
#ifdef and #endif control conditional compilation. This happens during an initial pass over the program, making dumb textual substitutions before the compiler even begins to consider the file to contain C code specifically. In this case, without the symbol defined only whitespace is left. The text is never even lexed into C tokens if the preprocessor define tested for isn't defined at that point.
You can see this for yourself: just invoke your compiler with whatever flag it uses to stop after preprocessing - e.g. gcc -E x.cc - and at that point in the output there will just be an empty line or two. This is also a very important technique for understanding macros, and a good thing to do when you just can't guess why some program's not working the way you expect - the compiler says some class or function doesn't exist and you've included its header - look at the preprocessed output to know what your compiler is really dealing with.
if DEBUG_MODE is not defined, the code under it will not be compiled.
What is the function of #?
It denotes a preprocessor directive:
One important thing you need to remember is that the C preprocessor is not part of the C compiler.
The C preprocessor uses a different syntax. All directives in the C preprocessor begin with a pound sign (#). In other words, the pound sign denotes the beginning of a preprocessor directive, and it must be the first nonspace character on the line.
# was probably chosen arbitrarily as an otherwise unused character in C syntax. # would have worked just as well, I presume.
If there wasn't a character denoting it, then there would probably be trouble differentiating between code intended for the preprocessor -- how would you tell whether if (FOO) was meant to be preprocessed or not?
Because # is the standard prefix for introducing preprocessor statements.
In early C compilers, the pre-processor was a separate program which would handle all the preprocessor statements (similar to the way early C++ "compilers" such as cfront generated C code) and generate C code for the compiler (it may still be a separate program but it may also be just a phase of the compiler nowadays).
The # symbol is just a useful character that can be recognised by the preprocessor and acted upon, such as:
#include <stdio.h>
#if 0
#endif
#pragma treat_warnings_as_errors
#define USE_BUGGY_CODE
and so on.
Preprocessor directives are lines included in the code of our programs that are not program statements but directives for the preprocessor. These lines are always preceded by a hash sign (#). The preprocessor is executed before the actual compilation of code begins, therefore the preprocessor digests all these directives before any code is generated by the statements.
Source: http://www.cplusplus.com/doc/tutorial/preprocessor/
It's because # is an indicator that its a preprocessor statement
meaning before it compiles your code, it is going to include the file stdio.h
# is a pre-processor directive. The preprocessor handles directives for source file inclusion (#include), macro definitions (#define), and conditional inclusion (#if).
When the pre-processor encounters this, it will include the headers, expand the macros and proceeds towards compilation. It can be used for other purposes like halting compilation using the #error directive. This is called conditional compilation.
We know, without preprocessor programm do not run. And preprocessor is # or #include or #define or other. So # is required before #include .