#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*/
#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*/
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 understandsizeof
, as#define
is just for text replacement. Preprocessor searchessize
macro (defined in#define
) in the source code, and replaces it with what it is defined to be, which is in your casesizeof(x)/sizeof(x[0])
.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.
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:
and use it:
the preprocessor performs a textual substitution that is handed to the compiler:
#define
is merely text replacement.#if
being a conditional preprocessor directive evaluatessizeof()
but at the time of preprocessing the preprocessor has no idea whatsizeof()
is. Preprocessor runs before the lexical analysis phase.sizeof is replaced at compile time. Preprocessing runs before compile starts.
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 you generate assembly, you will find that
sizeof < 2
compiles the function andsizeof >= 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:or
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 into0
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.