If-directive macro comparison

心不动则不痛 提交于 2021-01-20 22:12:30

问题


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
}

回答1:


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.




回答2:


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]




回答3:


In a #if statement, any identifier that remains after macro substitution (except for true and false) are replaced with the constant 0. So your directive becomes

#if 0 == 0

which is true.




回答4:


To accomplish what you are after, try this:

#include <iostream>
#define DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

In this case you can turn the debugging statements off by changing the "define" to "undef".

#include <iostream>
#undef DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

You might find that your compiler allows you to define DEBUG outside the code itself, at which point you can reduce the code to

#include <iostream>

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

And then invoke the compiler with an option such as -DDEBUG=0

Check out the chapter on Defensive Programming in Steve McConnell, "Code Complete."



来源:https://stackoverflow.com/questions/60779032/if-directive-macro-comparison

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!