8

使用 -Wall -pedantic

#include <limits.h>
#include <stdio.h>

int main(void)
{
    enum x {
        a,
        max = INT_MAX,
        out_1
    };
    enum y {
        b,
        out_2 = INT_MAX + 1
    };


    printf("%d %d\n", out_1, out_2);
    return 0;
}

铿锵返回

demo.c:9:3: warning: overflow in enumeration value
                out_1
                ^

如您所见,编译器不会警告 out_2 溢出,他的值在编译时是未知的?

4

2 回答 2

3

在第一种情况下,编译器本身正在尝试选择一个导致溢出的整数,因此会警告您。它很可能在生产INT_MIN. 该标准允许 a 中的任何值signed int成为枚举常量(见底部)。

在第二个中,表达式(INT_MAX + 1)在分配给之前计算out_2。此处表达式中的溢出会产生允许的结果,但这是未定义的行为。然后将有效结果存储在枚举中,这就是不产生第一个错误的原因。

clang (3.2) 也不会对此发出警告,这实际上是相同的:

int a = INT_MAX + 1;

在这方面,clang 的行为不符合 C 标准,因为这是未定义的。

比较 gcc 的输出使差异完全清楚:

In function ‘main’:
9:9: error: overflow in enumeration values
13:25: warning: integer overflow in expression [-Woverflow]

英特尔编译器会忽略枚举溢出,但会警告整数溢出:

enum.c(13): warning #61: integer operation result is out of range
      out_2 = INT_MAX + 1
                      ^


作为参考,来自 C99 标准 6.7.7.2.2,“定义枚举常量值的表达式应为整数常量表达式,其值可表示为int;.3,”枚举器列表中的标识符被声明作为具有类型的常量,int并且可能出现在任何允许的地方。”即枚举常量可以是任何int值,并且具有int类型。定义的枚举变量的结果类型可以是charintunsigned int,只要它允许所有可能的枚举中的常量。因此enums,示例中的两个都是未定义的,因为它们都需要整数溢出。第一个是明确非法的。

于 2013-03-08T21:33:42.183 回答
0

ISO C 将整数指定为枚举值。

如果您的编译器允许(并且 GCC 和 Clang 允许),那么 INT_MIN 是一个非常好的值。

如果编译器不允许指定索引,则需要发出错误

显式请求的 INT_MIN 很好但来自 INT_MAX 前身的自动增加值发出警告的原因是,该标准需要+1行为。

于 2013-03-08T21:47:52.437 回答