Wednesday, 21 January 2015

Conditionalising C/C++ code: "#ifdef FOO" vs. "#if FOO"

Is it better to use #ifdef PLATFORM or #if PLATFORM when writing code that needs to be conditionalised according to OS, CPU architecture, etc.?

Chromium's codebase uses the former. For example, it uses #ifdef OS_WIN or #if defined(OS_WIN), where OS_WIN is #defined on Windows (by build/build_config.h) and undefined elsewhere.

In contrast, NaCl's codebase uses the latter. It uses #if NACL_WINDOWS or if (NACL_WINDOWS), where NACL_WINDOWS is always #defined: as 1 on Windows and 0 elsewhere.

This latter approach has the benefit of catching some mistakes:

  • If you mistype the macro name in #if NACL_WINDOWS, you can get a compiler warning.

    However, this only works if you enable GCC/Clang's -Wundef warning. Microsoft's compiler (MSVC) has a similar warning, /wd4668, but it's effectively unusable because it produces warnings about system header files.

  • You can sometimes write if (PLATFORM) instead of #if PLATFORM. The if() version has the advantage that the code in the if() block will be compile-tested on all platforms, not just those where PLATFORM == 1. This can help catch mistakes earlier.

    This doesn't work if the code block uses functions that are only defined on PLATFORM, though.

See also: The Great -Wundef purge