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