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):
3) Preprocessing directives of the forms
# if constant-expression new-line group
opt
# elif constant-expression new-line group
opt
check whether the controlling constant expression evaluates to nonzero.
4) Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the
defined
unary operator), just as in normal text. If the tokendefined
is generated as a result of this replacement process or use of thedefined
unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. After all replacements due to macro expansion and thedefined
unary operator have been performed, all remaining identifiers (including those lexically identical to keywords) are replaced with the pp-number 0, and then each preprocessing token is converted into a token. [...]
So, for example, expressions like this:
#if !FOO
Will evaluate to 1
if FOO
is undefined, since it will be treated as a 0, and then !FOO
would be evaluated as !0
, which is 1
.
#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
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