With #if
identifiers that are not macros are all considered to be the number zero
. The gcc docs for #if lay out the requirements nicel, which says (emphasis mine going forward):
#if expression
expression is a C expression of integer type, subject to stringent restrictions. It may contain
- Integer constants.
- Character constants, which are interpreted as they would be in normal code.
- Arithmetic operators for addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and logical operations (&& and ||). The latter two obey the usual short-circuiting rules of standard C.
- Macros. All macros in the expression are expanded before actual computation of the expression's value begins.
- Uses of the defined operator, which lets you check whether macros are defined in the middle of an ‘#if’.
- 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.
and notes that:
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’.
This is covered in the draft C99 standard section 6.10.1
Conditional inclusion paragraph 4 which says:
[...]After all replacements due to macro expansion and the defined 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.[...]