Why is the #if
condition in the following code fulfilled:
#include <iostream> #define VALUE foo int main() { #if VALUE == bar std::cout << "WORKS!" << std::endl; #endif // VALUE }
The #if directive, with the #elif, #else, and #endif directives, controls compilation of portions of a source file. If the expression you write (after the #if) has a nonzero value, the line group immediately following the #if directive is kept in the translation unit.
In the C Programming Language, the #endif directive is used to define the following directives: #if, #ifdef , and #ifndef . Whenever the #endif directive is encountered in a program, it determines if the preprocessing of #if, #ifdef, or #ifndef has been completed successfully.
8.2 Conditional Compilation (#if, #ifdef, #ifndef, #else, #elif, #endif, and defined) Six directives are available to control conditional compilation. They delimit blocks of program text that are compiled only if a specified condition is true. These directives can be nested.
If expression is zero, the opposite happens. You can use ' #else ' with ' #ifdef ' and ' #ifndef ', too.
The page on cppreference.com states:
After all macro expansion and evaluation of defined and __has_include (since C++17) expressions, any identifier which is not a boolean literal is replaced with the number 0 (this includes identifiers that are lexically keywords, but not alternative tokens like and).
So VALUE
is first replaced with foo
, and then both foo
and bar
are replaced with 0.
This is because neither foo
nor bar
have been given any definition or value - so they are the same (i.e. replaced with a "0" value). Compilers will give warnings about this.
The MSVC
compiler (Visual Studio 2019) gives the following:
warning C4668: 'foo' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
warning C4668: 'bar' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
So VALUE
is given the value '0' (default for foo
) and bar
also has '0', so VALUE == bar
evaluates to "TRUE."
Similarly, clang-cl
gives the following:
warning : 'foo' is not defined, evaluates to 0 [-Wundef]
warning : 'bar' is not defined, evaluates to 0 [-Wundef]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With