使用-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;
}
clang返回
demo.c:9:3: warning: overflow in enumeration value
out_1
^
正如您所看到的,编译器没有警告out_2溢出,他的值在编译时是未知的?
答案 0 :(得分:2)
在第一个实例中,编译器本身正在尝试选择导致溢出的整数,因此警告您。它可能会产生INT_MIN
。该标准允许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
类型。定义的枚举变量的类型可以是char
,int
或unsigned int
,只要它允许枚举中的所有可能常量。因此,enums
中的{{1}}示例是未定义的,因为它们都需要整数溢出。第一个是明确非法的。
答案 1 :(得分:0)
ISO C将整数指定为枚举值。
如果您的编译器允许它(以及GCC和Clang),那么INT_MIN是一个非常好的值。
如果编译器不允许指定的索引,则需要发出错误。
显式请求INT_MIN正常但INT_MAX前任发出警告的自动增加值的原因是标准需要 +1 行为。< / p>