我如何找到 C++ 编译器认为定义为常量的内容?

How do I find something that the C++ compiler thinks is defined as a constant?

我在尝试构建我的应用程序时报告了以下错误:

对于以下代码:

namespace oP
{
      enum adjustment
      {
         AUTO_OFF,
         AUTO_ONCE,
         AUTO_CONTINUOUS,
         AUTO_SEMI,
         ABSOLUTE,        // The line that the errors point to.
         NUDGE
      };
}

小写 "absolute" 构建正常,如果我拼写错误 ABSOLUTE 则构建没有错误。

我搜索了我的整个代码库,没有其他地方使用术语 "ABSOLUTE"。 我调查了没有此更改的构建工件,但我在其中找不到任何对 ABSOLUTE 的引用。

有没有人指出问题所在或如何调试?

谢谢

ABSOLUTE#defined(到数字 1)在 windows API headers <windi.h> 之一。这就是让编译器感到困惑的地方。

您可以 #undef 它,如果不需要它,请删除 <windows.h>,或者重命名您的枚举。

您在其中一个包含的文件中的某处以该名称定义了一个宏;检查它们。更简单的方法是检查预处理器的输出。

如果您使用 GCC,请使用 -E 标志在预处理阶段后停止。使用 VC++ 编译器,您应该使用 /E and/or /P。有关详细信息,请参阅 How do I see a C/C++ source file after preprocessing in Visual Studio?


通常惯例是全部大写命名宏;这也适用于枚举,如果 你使用 C++03 的(普通)枚举。更好的选择是使用 C++11 的强类型 scoped enumerations.

每个条目的名称都可以是 Pascal 大小写,并且通过枚举的名称修饰,它们变得非常易读 Adjustment::Absolute,而不是旧的、无范围的枚举 ABSOLUTE。这不是很可读,因为 reader 可能会将自己与 wingdi.h 声明的宏混淆(正如 Bathsheba 指出的那样)。除了可读性之外,它还避免了污染封闭的命名空间。

你正在使用 visual c++ 编译器和 #include 那么你应该会得到这个错误。在 windows.h 中包含文件 #include < wingdi.h>,在 wingdi.h 中你会发现

/* Coordinate Modes */
#define ABSOLUTE            1
#define RELATIVE            2

因此发生错误。

How do I find something that the C++ compiler thinks is defined as a constant?

如果您的编译器不愿意生成有用的消息(通常它会在之前定义术语的地方打印)或者如果您怀疑自己成为了 WinAPI 宏巫术的受害者 headers...

有选择地注释掉代码行并重新编译以查明问题所在。 如果您注释掉一行并且您的程序在那之后编译,那么 that 行就是问题的根源。如果您的代码块很大,请执行 "binary search" - 注释掉整个块,然后是一半,这样您可以快速缩小问题范围。

在 IDE 中,您通常可以将鼠标悬停在项目上以查看它的定义位置,或者按一个键或使用上下文菜单 "jump to definition"。

除此之外,您还可以研究预处理器输出。


and can't selectively comment out headers to test when it changes - since the new list of compiler warnings would be too onerous to work through

创建一个空白的 *.cpp 文件并将有问题的定义复制到其中,直到你破坏它。这将使您能够查明问题所在。

在您自己的 *.h 文件中始终只包含必要的最小集合 headers 是一个很好的做法,最好完全避免 OS-specific headers,尽管那不是在这种情况下真的有可能。

在您的特定情况下,另一个不错的选择是更改枚举值的命名样式。通常 ALL_UPPERCASE 只为宏保留(宏定义和宏常量)。此规则的一个值得注意的例外是 Windows headers 中定义的 minmax 宏(它们可以被禁用)。因为您在 enum 中使用了它,所以您与 OS-specific 定义发生冲突。我会对枚举使用与常量和局部变量相同的命名约定。