Question

Let's say I have the following piece of code. Is it correct to say that the conditional directive always evaluates to zero since M is expanded before compile time where the value of i is zero according to C specification? Could someone explain it if I'm wrong:

#include <stdio.h>

#define M i

int main() {
    int i = 10;
    #if M == 0
     i = 0;
    #endif
    printf("%d", i);
    return 0;
}
Was it helpful?

Solution

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.[...]

OTHER TIPS

Yes, they are treated as the number 0.

C11 §6.10.1 Conditional inclusion

... 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.

pp-number here refers to preprocessing numbers in §6.4.8.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top