Search code examples
cpreprocessor

How to test C Preprocessor -D flag value?


I have the following .c file:

$ cat hellomake.c 
#include <stdio.h>

#ifdef REVISION
#warning defined
#else
#warning not defined
#endif

#if REVISION==C0
#warning using C0
char str[] = "c0";
#else
#warning using B0
char str[] = "b0";
#endif

void main(void)
{
    printf("%s\n", str);
}

I build it using this Makefile:

$cat Makefile 
REVISION=B0

all: hellomake.c
    gcc -o hellomake hellomake.c -DREVISION=$(REVISION)

Build shows that preprocessor goes through the #if REVISION==C0 branch, not through the #else branch:

$ make all
gcc -o hellomake hellomake.c -DREVISION=B0
hellomake.c:4:2: warning: #warning defined [-Wcpp]
    4 | #warning defined
      |  ^~~~~~~
hellomake.c:10:2: warning: #warning using C0 [-Wcpp]
   10 | #warning using C0
      |  ^~~~~~~

Executing the binary also shows the same odd behavior:

$ ./hellomake 
c0

My question is, how is this possible ? Why does the #if REVISION==C0 value test not work properly ? I am expecting the preprocessor to print "using B0" and the binary execution to result in "b0".


Solution

  • The C preprocessor does not do string comparisons. Instead, B0 and C0 are interpreted as undefined macro identifiers, with the value 0. Thus when REVISION==C0 is expanded to B0==C0 this becomes 0==0 which is true. If you want something comparable, you would need to use integers. See: https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_4.html#SEC38