13

我有一些代码要移植到一个新平台,它开始给我一个关于比较来自两个不同枚举器列表的两个枚举器的错误。我很困惑为什么它给我一个错误。

C 规范(6.7.2.2)的枚举规范部分指出:

枚举器列表中的标识符被声明为具有 int 类型的常量,并且可以出现在任何允许的地方。127)带有 = 的枚举器将其枚举常量定义为常量表达式的值。如果第一个枚举数没有 =,则其枚举常数的值为 0。

所以我应该能够使用与 int 常量相同的枚举成员。在这个小示例程序中:

enum first {
  a,
  b
};

enum second {
 c,
 d
};

int main(){
    enum first myf = a;
    enum second mys = c;

    if(myf == mys)
        printf("same value\n"); 
    return 0;
}

编译时gcc -Wall -Werror我收到消息:

错误:'enum first' 和 'enum second' 之间的比较 [-Werror=enum-compare]

我知道,如果我对两者myfmysasint进行类型转换,编译器会很高兴,就像我可以使用 andint的值设置几个 smyfmys进行比较一样;但为什么我必须做这些来摆脱警告?为什么这个警告首先存在?这样做肯定有一些我没有看到的危险。


注意:
我已经阅读了关于这个 enum-compare 标志的 gcc 文档,但它并没有说明什么:

-Wenum-compare
警告不同枚举类型的值之间的比较。在 C++ 中,条件表达式中的枚举不匹配也会被诊断出来,并且默认情况下会启用警告。在 C 中,此警告由 -Wall 启用。

4

4 回答 4

17

由于标准合规性问题,这不是警告,它是“这似乎不正确”的警告之一。如果您考虑枚举的典型用途,那么在许多情况下进行这样的比较并没有多大意义。例如:

enum Day {
  Sunday,
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday
};

enum Month {
  January,
  February,
  March,
  April,
  May,
  June,
  July,
  August,
  September,
  October,
  November,
  December
};

enum Day day = Wednesday;
enum Month month = April; 

if (day == month) { ... }

这评估为真,但一般来说,比较没有多大意义。正如您所指出的,如果您知道您的意思,则类型转换将说服编译器。

于 2013-04-02T19:44:22.240 回答
2

它在警告您,因为您打开了警告标志。标志描述没有解释它为什么存在,但假设它的存在可能是安全的,以防止不同枚举类型之间的意外比较,因为这通常是一个错误。

此外,您可以使用与 int 常量相同的枚举值是正确的。如果你说if (myf == c)那么它很可能不会发出警告(我说很可能是因为我没有尝试过,而且 GCC 老实说可以用那个警告做它想做的任何事情,但从技术上讲c它只是一个积分常数并且不携带类型enum second)。但相反,您是在显式比较不同枚举类型的两个值。

于 2013-04-02T19:42:35.497 回答
2

if((int)myf == (int)mys)

那应该这样做。但这是一种肮脏的做法,只有在两个枚举都是同一组的不同“版本”时才使用它,就像新的枚举最后会包含新的关键字一样。

于 2013-04-02T19:56:28.143 回答
1

它是一个警告,但是当您使用 -Wall -Werror 进行编译时,所有警告都被视为错误 Rest 您可以在类似的问题中找到一些东西。

比较两个不同的枚举时是否有正确的方法来避免警告?

带着敬意

他的

于 2013-04-02T19:49:56.950 回答