Search code examples
c++cc++11preprocessor

Do 'true' and 'false' have their usual meaning in preprocessor conditionals?


Given a C++11 compiler, which #error is the correct one it should end up with?

// no #includes!
#define SOMEMACRO true
#if SOMEMACRO
  #error "it was true"
#else
  #error "it was false"
#endif

Godbolt demo

Obviously I'm using #error just as a test. I know true and false are defined in the language proper, but this is preprocessor context. In C99 it seems not to be recognised by the preprocessor.

I'm asking because it seems that all compilers I tried see it as 'true', while a static code analysis tool insists that true isn't defined, implicitly false and ends up in "it was false".


Solution

  • In all ISO C++ standards, both true and false are keyword constants, just like nullptr in C++11. So #if SOMEMACRO = #if true and the preprocessor will go to the truthy branch.

    In C, however, neither true nor false is ever a keyword. They're macros defined to 1 and 0 respectively, as of C99 and with #include <stdbool.h>. This does mean that however, if you don't include stdbool.h, the compiler should complain about unrecognized identifiers for true, false etc. After including the header, #if SOMEMACRO is now #if 1, which is truthy in C.

    For preprocessing, this quote from CppReference is meaningful:

    Any identifier, which is not literal, non defined using #define directive, evaluates to 0.

    So in your (probably C-oriented) static analysis tool, it sees true as a non-#define-defined identifier, and therefore evaluates true to zero. You're not going to observe this behavior if you use a C++ analysis tool.

    In that case, you probably shouldn't have missed the #include <stdbool.h> in the first place, though.