While learning about the C preprocessor #if
, I came across this particular statement describing the term expression in its syntax given on the GCC site, syntax:
#if *expression*
controlled text
#endif
What does the following statement mean in context of expression described in the above syntax?
statement: In C, an expression may contain identifiers that are not macros, which are all considered to be the number zero. This allows you to write #if MACRO
instead of #ifdef MACRO
, if you know that MACRO, when defined, will always have a nonzero value. Function-like macros used without their function call parentheses are also treated as zero.
In some contexts this shortcut is undesirable. The
-Wundef option causes GCC to warn whenever it encounters an identifier which is not a macro in an #if
.
In C , expression may contain Identifiers that are not macros, which are all considered to be the number zero.
This means that, if you have a #if
directive such as:
#if X == 3
and X
is not defined as a preprocessor macro, then it is replaced with 0
, so the directive is processed as if it were:
#if 0 == 3
That is standard C behavior. GCC’s -Wundef
option asks the compiler to warn you when this occurs.
There is one exception; the identifier defined
is treated specially. If defined identifier
or defined (identifier)
appears in a #if
directive, it is replaced by 1 or 0 according to whether identifier
is a defined macro or not.
This allows you to write
#if MACRO
instead of#ifdef MACRO
, if you know that MACRO, when defined, will always have a nonzero value.
Due to the above substitution, #if MACRO
will become either #if replacement
if MACRO
is a defined object-like macro or #if 0
if not. Then we have the following cases:
MACRO
is an object-like macro that expands to something that is not zero: #if MACRO
evaluates it as true, and #ifdef MACRO
evaluates its condition as true.MACRO
is an object-like macro that expands to something that is zero: #if MACRO
evaluates it as false, and #ifdef MACRO
evaluates its condition as true.MACRO
is not defined as an object-like macro: #if MACRO
becomes #if 0
and is evaluated as false, and #ifdef MACRO
evaluates its condition as false.Thus, #if MACRO
and #ifdef MACRO
behave the same if MACRO
is not an expression with value zero.
Note: An object-like macro has no arguments, as in:
#define MACRO (3+4)
and a function-like macro has arguments, as in:
#define MACRO(x) (3+(x))
Function-like macros used without their function call parentheses are also treated as zero.
If MACRO
is defined as a function-like macro, then, in #if MACRO
, no macro replacement is performed. This is because function-like macros are replaced only if they are followed by parentheses, as in #if MACRO(3)
. So, after being rejected for macro replacement, it proceeds to the substitution of identifiers with 0
, becoming #if 0
.