sizeof() is not executed by preprocessor
开发者_如何转开发#if sizeof(int) != 4
/* do something */
Using sizeof inside #if
doesn't work while inside #define
it works, why?
#define size(x) sizeof(x)/sizeof(x[0]) /*works*/
Nothing is evil - everything can be misused, or in your case misunderstood. The sizeof
operator is a compiler feature, but compiler features are not available to the preprocessor (which runs before the compiler gets involved), and so cannot be used in #if
preprocessor directives.
However, when you say:
#define size(x) sizeof(x)/sizeof(x[0])
and use it:
size(a)
the preprocessor performs a textual substitution that is handed to the compiler:
sizeof(a)/sizeof(a[0])
C "Preprocessor" Macros Only Evaluate Constants and Other Macros
The short answer is a preprocessor expression only provides a meaningful evaluation of an expression composed of other preprocessor macros and constants.
Try this, you will not get an error:
#if sizeof < 2
int f(int x) { return x; }
#endif
If you generate assembly, you will find that sizeof < 2
compiles the function and sizeof >= 2
does not. Neither returns an error.
What's going on? It turns out that, except for preprocessor macros themselves, all identifiers in a preprocessor ("macro") expression are replaced with 0. So the above #if
is the same as saying:
#if Easter_Bunny < 2
or
#if 0 < 2
This is why you don't actually get any sort of error when mistakenly using the sizeof
operator in a preprocessor expression.
As it happens, sizeof
is an operator, but it's also an identifier, and identifiers that are not themselves macros all turn into 0
in preprocessor expressions. The preprocessor runs, at least conceptually, before the compiler. It can turn non-C syntax into C so at the point it is running, the C program hasn't even been parsed yet. It isn't possible to reference actual C objects yet: they don't exist.
And naturally, a sizeof
in the replacement text of a definition is simply passed through to the compiler as, well, the replacement text where the macro is used.
The preprocessor cannot evaluate the results of the sizeof
operator. That is calculated by the compiler, long after the preprocessor is finished.
Since the second expression results in a compile-time computation, it works. The first is an impossible test for the preprocessor.
#define
is merely text replacement. #if
being a conditional preprocessor directive evaluates sizeof()
but at the time of preprocessing the preprocessor has no idea what sizeof()
is. Preprocessor runs before the lexical analysis phase.
sizeof is replaced at compile time. Preprocessing runs before compile starts.
The compiler doesn't touch either line. Rather, the preprocessor rips through the file, replacing any instances of size(x) with your macro. The compiler DOES see these replacements.
Preprocessor doesn't know sizeof
operator, it just cannot understand it. So #if
doesn't work, since it has to understand it to work, because it is a conditional conditional preprocessor; it needs to know whether it evaluates to true or false.
But #define
doesn't need to understand sizeof
, as #define
is just for text replacement. Preprocessor searches size
macro (defined in #define
) in the source code, and replaces it with what it is defined to be, which is in your case sizeof(x)/sizeof(x[0])
.
The reason it doesn't work is because the pre-processor macros are 'evaluated' in a pass before the code reaches the compiler. So in the if pre-processor directive, the sizeof(int) (actually the sizeof(int) != 4) cannot be evaluated because that is done by the compiler, not the pre-processor.
The define statement though, simply does a text substitution, and so when it comes to the compiler, everywhere you had 'size(x)' you would have 'sizeof(x)/sizeof(x[0])' instead, and then this evaluates there at the compile stage... at every point in the code where you had 'size(x)'
If you want to check the size of the integer in the processor, use your make system to discover the size of integer on your system before running the preprocessor and write it to a header file as e.g. #define SIZEOF_INT 4
, include this header file and do #if SIZEOF_INT == 4
For example, if you use cmake, you can use the CMAKE_SIZEOF_INT
variable which has the size of the integer which you can put in a macro.
精彩评论