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