c

Preprocessors in C #if and #ifdef


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.


Solution

  • 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:

    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.