Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If-directive macro comparison

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 } 
like image 680
michalt38 Avatar asked Mar 20 '20 17:03

michalt38


People also ask

What is #if and #endif?

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.

What is the use of #if and #endif in C?

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.

What purpose do #if #elseif #else #endif #ifdef #ifndef serve?

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.

Can you use else for Ifdef?

If expression is zero, the opposite happens. You can use ' #else ' with ' #ifdef ' and ' #ifndef ', too.


2 Answers

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.

like image 62
eesiraed Avatar answered Oct 04 '22 12:10

eesiraed


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]

like image 24
Adrian Mole Avatar answered Oct 04 '22 14:10

Adrian Mole