The gcc docs for cpp explain about the #if
directive:
[...] and logical operations (&& and ||). The latter two obey the usual short-circuiting rules of standard C.
What does that mean? There is no evaluation of expressions during preprocessing, so how can it be short-circuited?
Like C, Perl provides the && (logical AND) and || (logical OR) operators. They evaluate from left to right (with && having slightly higher precedence than || ) testing the truth of the statement.
In imperative language terms (notably C and C++), where side effects are important, short-circuit operators introduce a sequence point – they completely evaluate the first argument, including any side effects, before (optionally) processing the second argument.
Short-Circuit Evaluation: Short-circuiting is a programming concept in which the compiler skips the execution or evaluation of some sub-expressions in a logical expression. The compiler stops evaluating the further sub-expressions as soon as the value of the expression is determined.
The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation. It is called a macro processor because it allows you to define macros, which are brief abbreviations for longer constructs.
Very simple: undefined macros have numeric value zero, and division by zero is illegal.
#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42 #define USE_CELLPOOL #endif
#if
does evaluate the rest of its line as an integer constant expression. Your linked documentation begins:
The ‘#if’ directive allows you to test the value of an arithmetic expression, rather than the mere existence of one macro.
That isn't a gcc extension, the Standard's syntax for #if
is
#if
constant-expression new-line group
opt
.
The C99 preprocessor treats all constants as [u]intmax_t
.
What they are referring to is &&
and ||
operators for #if
#if defined (AAA) || defined (BBB)
If defined (AAA)
is defined then defined (BBB)
is never evaluated.
UPDATE
So running the calculation will be short circuited. For example, if you build with -Wundef
to warn about the usage of undefined macros.
#if defined FOO && FOO > 1000 #endif #if FOO > 1000 #endif
will result in
thomas:~ jeffery$ gcc foo.c -Wundef foo.c:4:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef] #if FOO > 1000 ^ 1 warning generated.
So the first version does not generate the undefined macro warning, because FOO > 1000
is not evaluated.
OLD MUSINGS
This become important if the second part is a macro which has side effects. The macro would not be evaluated, so the side effects would not take place.
To avoid macro abuse I'll give a somewhat sane example
#define FOO #define IF_WARN(x) _Pragma (#x) 1 #if defined(FOO) || IF_WARN(GCC warning "FOO not defined") #endif
Now that I constructed this example, I now run into a problem. IF_WARN
is always evaluated.
huh, more research needed.
Well foo… now that I read it again.
Macros. All macros in the expression are expanded before actual computation of the expression's value begins.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With