Given the C file below:
$ cat macros.c
#ifdef MACRO
# error MACRO is defined
#else
# error MACRO is undefined
#endif
#if MACRO
# error MACRO is non-zero
#else
# error MACRO is zero
#endif
What is the expected output of the following?
$ gcc -c macros.c
$ gcc -DMACRO -c macros.c
$ gcc -DMACRO=0 -c macros.c
Answer: Here's what the gcc's preprocessor on my machine does.
$ gcc -c macros.c
macros.c:4:4: error: #error MACRO is undefined
macros.c:9:4: error: #error MACRO is zero
$ gcc -DMACRO -c macros.c
macros.c:2:4: error: #error MACRO is defined
macros.c:7:4: error: #error MACRO is non-zero
$ gcc -DMACRO=0 -c macros.c
macros.c:2:4: error: #error MACRO is defined
macros.c:9:4: error: #error MACRO is zero
$
Lesson: #ifdef MACRO
evaluates to true for defined-ness even if the defined value is 0 (zero).
Another C preprocessor gotcha! Is this how it should be as per the C standard?
Any undefined macro is treated as it were defined as 0 for the purposes of evaluating the controlling expressions of
#if
statements. From C99 §6.10.1/3-4 (emphasis added):So, for example, expressions like this:
Will evaluate to
1
ifFOO
is undefined, since it will be treated as a 0, and then!FOO
would be evaluated as!0
, which is1
.#ifdef
only cares if MACRO has been defined or not. Value doesn't matter.#if
checks for the value of MACRO and evaluates MACRO accordingly.That is correct behaviour
The behavior is as per the standard.
C99 Standard: 6.10.1 Conditional inclusion:
Para 2: Preprocessing directives of the forms
check whether the controlling constant expression evaluates to nonzero.
Para 4: Preprocessing directives of the forms
check whether the identifier is or is not currently defined as a macro name. Their conditions are equivalent to
#if defined
identifier and#if !defined
identifier respectively.