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
的数值。实际上,这不太可能溢出底层整数类型(int
、char
、unsigned char
或编译器选择的任何内容),因此使用 %d
格式打印值将打印 7
.
但是,不存在值为 7
的类型 enum week
的枚举(命名)值。
如果递增枚举值会溢出基础整数类型(此处不是这种情况),则结果未定义。这是因为基础整数类型可能是有符号或无符号的,溢出有符号整数类型会导致未定义的行为。
理论上,编译器可能会使用 enum week
的基础类型,它只能表示值 0
到 6
- 在这种情况下递增 saturday
给出未定义的行为。实际上,AFAIK,还没有任何 C 编译器不选择底层类型作为标准整数类型之一(char
、int
、unsigned char
、unsigned
,等等)。所有这些类型都可以表示 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
,并且要求类型char
、unsigned char
、signed char
没有填充位,每个字符类型的范围必须至少涵盖 0
到 127
。更宽的整数类型(short
、int
等)的范围至少与 signed char
或 unsigned 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
.
如果我有枚举类型,例如:
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
的数值。实际上,这不太可能溢出底层整数类型(int
、char
、unsigned char
或编译器选择的任何内容),因此使用 %d
格式打印值将打印 7
.
但是,不存在值为 7
的类型 enum week
的枚举(命名)值。
如果递增枚举值会溢出基础整数类型(此处不是这种情况),则结果未定义。这是因为基础整数类型可能是有符号或无符号的,溢出有符号整数类型会导致未定义的行为。
理论上,编译器可能会使用 enum week
的基础类型,它只能表示值 0
到 6
- 在这种情况下递增 saturday
给出未定义的行为。实际上,AFAIK,还没有任何 C 编译器不选择底层类型作为标准整数类型之一(char
、int
、unsigned char
、unsigned
,等等)。所有这些类型都可以表示 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
,并且要求类型char
、unsigned char
、signed char
没有填充位,每个字符类型的范围必须至少涵盖 0
到 127
。更宽的整数类型(short
、int
等)的范围至少与 signed char
或 unsigned 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
.