是枚举 { a } e = 1;有效的?
Is enum { a } e = 1; valid?
一个简单的问题:enum { a } e = 1;
有效吗?
换句话说:在枚举常量的值集中不存在的值是否会导致明确定义的行为?
演示:
$ gcc t0.c -std=c11 -pedantic -Wall -Wextra -c
<nothing>
$ clang t0.c -std=c11 -pedantic -Wall -Wextra -c
<nothing>
$ icc t0.c -std=c11 -pedantic -Wall -Wextra -c
t0.c(1): warning #188: enumerated type mixed with another type
# note: the same warning for enum { a } e = 0;
$ cl t0.c /std:c11 /Za /c
<nothing>
来自6.7.2.2中的C18标准:
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.
所以 enum { a } e = 1;
是有效的。 e
是 'integer' 类型,因此它可以取值 1
。 1
不作为枚举值存在这一事实没有问题。
枚举成员只为一些可能的值提供方便的标识符。
我在this Draft C11 Standard (in terms of "constraints") that prohibits an assignment to a enum
type such as yours (and the C18 Standard quoted in 中找不到任何参考使用基本相同的措辞)。
但是,C11 草案确实在 附件 I – 常见警告中提供了这一点:
1 An implementation may generate warnings in many
situations, none of which are specified as part of this International
Standard. The following are a few of the more common situations.
2
…
— A value is given to an object of an
enumerated type other than by assignment of an enumeration constant
that is a member of that type, or an enumeration object that has the
same type, or the value of a function that returns the same enumerated
type (6.7.2.2).
但是建议的警告同样适用于 enum { a } e = 0;
这样的赋值,其中 RHS 的 值 对应于 一个有效的枚举常量,但它 实际上 既不是该类型的枚举常量,也不是该枚举类型的对象。
在 C 中有效
这在 C 中有效,例如202x working draft:
6.7.2.2/4 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
特别是由于“兼容类型”要求:
6.2.7/1 Two types have compatible type if their types are the same. Additional rules [...]
... implementation-defined 和 C++14 和 earlier/C++17 及更高版本中可能的 unspecified/undefined 行为
虽然超出了此问答的范围(C 标记,而不是 C++),但有趣的是要指出 C++ 并不适用,其中“C 风格”无范围枚举没有固定的底层类型具有微妙的意义与C的区别,C++案例详见以下Q&A:
简而言之
根据枚举类型的定义、兼容类型的转换规则和兼容性保证,1
的特定值保证了enum { a } e = 1;
的有效性,综合了不同的原因。
剧透警报:在 C18 中,它比任何单个段落的引用都复杂得多(请参阅我在接受的答案下的评论)。
完整解释
我将逐步引用C18标准(准确地说是N2176)。亮点来自我。
首先,我们知道enum { a }
是一个整数类型:
6.2.5. Types
16: An enumeration comprises a set of named integer constant values. Each distinct enumeration constitutes a different enumerated type.
17: The type char, the signed and unsigned integer types, and the enumerated types are collectively called integer types.
然后,我们可以证明如果 enum { a }
是一个“足够大”以容纳 1
的整数类型,则赋值将有效(因为没有明确的相反声明):
6.2.7 Compatible types and composite types
1:Two types have compatible type if their types are the same. (...)
6.3. Conversions
2: Unless explicitly stated otherwise, conversion of an operand value to a compatible type causes no change to the value or the representation.
6.7.2.2 Enumeration specifiers
4: 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.
但是字体够大吗?从这里我们推导出a
的值为0
。由于它也是集合中最大的枚举常量,我们可以推断 enum { a }
“至少”与 char
兼容:
6.7.2.2 Enumeration specifiers
3: (...) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant.
总之,赋值是合法的,因为文字1
也兼容char
。
注意依赖于实现的假设!
但请注意,这样的整数赋值不一定对您选择的任何整数有效:
enum { a } = INT_MAX; // Implementation dependent, see J.3.9
enum { a, b=INT_MAX } = 1024; // ok: b requires int as compatible type
第一种情况,枚举只保证兼容char
。但我们无法保证它与 int
:
兼容
J.3. Implementation-defined behavior
(...)
**J.3.9. Structures, unions, enumerations, and bit-fields
(...)
- The integer type compatible with each enumerated type (6.7.2.2).
在第二种情况下,我们使用了一个整数值的规范来强制与 int
兼容的类型。
一个简单的问题:enum { a } e = 1;
有效吗?
换句话说:在枚举常量的值集中不存在的值是否会导致明确定义的行为?
演示:
$ gcc t0.c -std=c11 -pedantic -Wall -Wextra -c
<nothing>
$ clang t0.c -std=c11 -pedantic -Wall -Wextra -c
<nothing>
$ icc t0.c -std=c11 -pedantic -Wall -Wextra -c
t0.c(1): warning #188: enumerated type mixed with another type
# note: the same warning for enum { a } e = 0;
$ cl t0.c /std:c11 /Za /c
<nothing>
来自6.7.2.2中的C18标准:
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.
所以 enum { a } e = 1;
是有效的。 e
是 'integer' 类型,因此它可以取值 1
。 1
不作为枚举值存在这一事实没有问题。
枚举成员只为一些可能的值提供方便的标识符。
我在this Draft C11 Standard (in terms of "constraints") that prohibits an assignment to a enum
type such as yours (and the C18 Standard quoted in
但是,C11 草案确实在 附件 I – 常见警告中提供了这一点:
1 An implementation may generate warnings in many situations, none of which are specified as part of this International Standard. The following are a few of the more common situations.
2
…
— A value is given to an object of an enumerated type other than by assignment of an enumeration constant that is a member of that type, or an enumeration object that has the same type, or the value of a function that returns the same enumerated type (6.7.2.2).
但是建议的警告同样适用于 enum { a } e = 0;
这样的赋值,其中 RHS 的 值 对应于 一个有效的枚举常量,但它 实际上 既不是该类型的枚举常量,也不是该枚举类型的对象。
在 C 中有效
这在 C 中有效,例如202x working draft:
6.7.2.2/4 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
特别是由于“兼容类型”要求:
6.2.7/1 Two types have compatible type if their types are the same. Additional rules [...]
... implementation-defined 和 C++14 和 earlier/C++17 及更高版本中可能的 unspecified/undefined 行为
虽然超出了此问答的范围(C 标记,而不是 C++),但有趣的是要指出 C++ 并不适用,其中“C 风格”无范围枚举没有固定的底层类型具有微妙的意义与C的区别,C++案例详见以下Q&A:
简而言之
根据枚举类型的定义、兼容类型的转换规则和兼容性保证,1
的特定值保证了enum { a } e = 1;
的有效性,综合了不同的原因。
剧透警报:在 C18 中,它比任何单个段落的引用都复杂得多(请参阅我在接受的答案下的评论)。
完整解释
我将逐步引用C18标准(准确地说是N2176)。亮点来自我。
首先,我们知道enum { a }
是一个整数类型:
6.2.5. Types
16: An enumeration comprises a set of named integer constant values. Each distinct enumeration constitutes a different enumerated type.
17: The type char, the signed and unsigned integer types, and the enumerated types are collectively called integer types.
然后,我们可以证明如果 enum { a }
是一个“足够大”以容纳 1
的整数类型,则赋值将有效(因为没有明确的相反声明):
6.2.7 Compatible types and composite types
1:Two types have compatible type if their types are the same. (...)6.3. Conversions
2: Unless explicitly stated otherwise, conversion of an operand value to a compatible type causes no change to the value or the representation.6.7.2.2 Enumeration specifiers
4: 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.
但是字体够大吗?从这里我们推导出a
的值为0
。由于它也是集合中最大的枚举常量,我们可以推断 enum { a }
“至少”与 char
兼容:
6.7.2.2 Enumeration specifiers
3: (...) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant.
总之,赋值是合法的,因为文字1
也兼容char
。
注意依赖于实现的假设!
但请注意,这样的整数赋值不一定对您选择的任何整数有效:
enum { a } = INT_MAX; // Implementation dependent, see J.3.9
enum { a, b=INT_MAX } = 1024; // ok: b requires int as compatible type
第一种情况,枚举只保证兼容char
。但我们无法保证它与 int
:
J.3. Implementation-defined behavior
(...) **J.3.9. Structures, unions, enumerations, and bit-fields
(...)
- The integer type compatible with each enumerated type (6.7.2.2).
在第二种情况下,我们使用了一个整数值的规范来强制与 int
兼容的类型。