【问题标题】:-Wundef does not warn about an undefined symbol in front of #ifdef-Wundef 不对#ifdef 前面的未定义符号发出警告
【发布时间】:2021-10-19 17:22:02
【问题描述】:

请考虑以下代码:

// program.cpp

#include <iostream>

int main() {
#ifdef LINUX
    std::cout << "Linux\n";
#elif MAC
    std::cout << "Mac\n";
#elif WINDOWS
    std::cout << "Windows\n";
#elif BSD
    std::cout << "BSD\n";
#else
    std::cout << "Something else\n";
#endif
    return 0;
}

如果我同时使用 clang 和 gcc 编译它,

clang++ -Wundef -DBSD -o program program.cpp
# or
g++ -Wundef -DBSD -o program program.cpp

我会收到未定义符号 MACWINDOWS 的警告,但不会收到符号 LINUX 的警告:

program.cpp:6:7: warning: 'MAC' is not defined, evaluates to 0 [-Wundef]
#elif MAC
      ^
program.cpp:8:7: warning: 'WINDOWS' is not defined, evaluates to 0 [-Wundef]
#elif WINDOWS
      ^
2 warnings generated.

根据gcc 手册页:

-Wundef 如果在“#if”指令中评估未定义的标识符,则发出警告。 这样的标识符被零替换。
  • 它说 in 是一个#if 指令。是不是因为LINUX 不在那个结构里面?

  • 如果是这种情况,我如何告诉编译器为未定义符号 LINUX 发出警告?


  • clang version 12.0.1
  • gcc (GCC) 11.1.0
  • Target: x86_64-pc-linux-gnu (artixlinux)

【问题讨论】:

  • #ifdef LINUX/#if defined(LINUX) 如果您对此发出警告,那将毫无意义...
  • 尝试将elif MAC 更改为elif defined(MAC)WINDOWSBSD 也是如此。这样,您的代码将测试是否定义了所有宏,而不是(现在)测试是否定义了 LINUX,同时测试其他宏扩展为的值。
  • @Jarod42 是的,你是对的!
  • @Peter 完全正确!没有定义(MAC),它会扩展符号,如果符号没有定义,编译器(或预处理器)首先发出警告,然后用0替换未定义的符号,这样分支就会被删除。

标签: c++ compiler-warnings preprocessor


【解决方案1】:

原因是您的预处理器代码询问LINUX 是否已定义。但是对于MACWINDOWSBSD,您无需检查符号是否已定义;相反,您的代码假定它已定义并要求它的

更改您的代码以使用#elif defined(…) 而不是#elif … 来修复警告。

【讨论】:

  • 所以,#ifdef 只询问符号是否已定义。看来,在#ifdef LINUX 中,符号未评估,因此没有警告。然而,对于#elif 的情况,符号被求值或者编译器要求它的值!为什么编译器要求它的值?是不是因为#elif 没有任何机制可以理解它在#ifdef 结构中?
  • @Ali #ifdef … 只是#if defined(…) 的快捷方式。没有#elifdef,所以你需要使用#elif defined(…)来代替。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 2016-01-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多