clang enum溢出

时间:2013-03-08 21:27:12

标签: c enums overflow

使用-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溢出,他的值在编译时是未知的?

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类型。定义的枚举变量的类型可以是charintunsigned int,只要它允许枚举中的所有可能常量。因此,enums中的{{1}}示例是未定义的,因为它们都需要整数溢出。第一个是明确非法的。

答案 1 :(得分:0)

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

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

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

显式请求INT_MIN正常但INT_MAX前任发出警告的自动增加值的原因是标准需要 +1 行为。< / p>