C 中枚举类型的溢出?

Overflow of an enum type in C?

如果我有枚举类型,例如:

enum week{ sunday=0, monday, tuesday, wednesday, thursday, friday, saturday};

我有:

enum week day;
day = saturday;
day++;

一天的价值是多少?

我只能找到 C89 规范的草案,我不是 C 专家,所以我可能会误解它。但是它的 3.5.2.2 部分说

The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. [...] Each enumerated type shall be compatible with an integer type.

我认为这意味着 day++ 将始终在这里产生 7(比 saturday 表示的值多一个)。

枚举类型本质上是一个命名的整数值。该枚举类型与可以表示所有命名值的基础整数类型相关联。该基础整数类型需要能够表示所有唯一命名值,但其实际类型是实现定义的。

在这种情况下,saturday 的数值将为 6。递增它将给出 7 的数值。实际上,这不太可能溢出底层整数类型(intcharunsigned char 或编译器选择的任何内容),因此使用 %d 格式打印值将打印 7.

但是,不存在值为 7 的类型 enum week 的枚举(命名)值。

如果递增枚举值会溢出基础整数类型(此处不是这种情况),则结果未定义。这是因为基础整数类型可能是有符号或无符号的,溢出有符号整数类型会导致未定义的行为。

理论上,编译器可能会使用 enum week 的基础类型,它只能表示值 06 - 在这种情况下递增 saturday 给出未定义的行为。实际上,AFAIK,还没有任何 C 编译器不选择底层类型作为标准整数类型之一(charintunsigned charunsigned,等等)。所有这些类型都可以表示 7.

的数值

给定:

enum week {
    sunday=0, monday, tuesday, wednesday, thursday, friday, saturday
};
enum week day = saturday;
day ++;

day 的值为 7

引用 2011 ISO C 标准,6.7.2.2 第 1 段:

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration.

_Bool是一个无符号整数类型,但是不符合这个特定枚举类型的要求。

由于要求CHAR_BIT的值至少为8,并且要求类型charunsigned charsigned char没有填充位,每个字符类型的范围必须至少涵盖 0127。更宽的整数类型(shortint 等)的范围至少与 signed charunsigned char 的范围一样宽。因此,与 enum week 兼容的实现定义类型必须具有不大于 0 的下限和不小于 127.

的上限

(WARNING: Language-lawyering follows.) 可能存在允许 扩展整数类型 范围比_Bool 但比 char 范围更窄。例如,我认为 一个大小为 8 位但只有 3 个值位的扩展整数类型是合法的。但是由于整数类型需要使用二进制表示,具有 3 个值位的无符号类型将能够表示从 0 到 7 的值,而具有 2 个值位的无符号类型将无法表示 [=31 的值=].由于 enum week 可以保存值 6,因此它也必须能够保存值 7。在不寻常的实现中,它 可能 无法表示值 8,但您不太可能遇到这样的实现。

基本上,鉴于整数类型使用纯二进制表示的要求,任何可以表示 6 的类型也可以表示 7,尽管它不会自动遵循它也可以表示8.