Vil*_*ray 8 c enums enumeration c99 language-lawyer
C99标准要求用于定义枚举常量值的表达式具有可表示为的值int.
在C99标准第6.7.2.2节第2 节中:
定义枚举常量值的表达式应为整数常量表达式,其值可表示为
int.
但是,枚举类型可以由实现定义为与任何整数类型兼容,包括那些值范围之外的整数类型int.
在C99标准第6.7.2.2节第2 节中:
每个枚举类型应与
char有符号整数类型或无符号整数类型兼容.
这意味着虽然您无法在a的范围之外显式设置枚举常量int的值,但是int如果实现将枚举类型与具有范围的整数类型兼容,则枚举常量的值可以在a的范围之外.在...之外int.
现在我知道一种方法来获取int枚举常量的set 范围之外的特定值:虚拟枚举器.
enum hack{
DUMMY0 = INT_MAX,
DUMMY1,
/* supply as many more dummy enumerators as needed */
...
/* declare desired enumerator */
FOOBAR
};
Run Code Online (Sandbox Code Playgroud)
这要归功于C99标准第6.7.2.2节第3段:
枚举器
=将其枚举常量定义为常量表达式的值.
...
每个后续的枚举器都没有=将其枚举常量定义为通过将1添加到前一个枚举常量的值而获得的常量表达式的值.
不幸的是,这仅适用于大于的正值INT_MAX,因为每个后续枚举器的值只会递增.另一个需要注意的是,需要创建可能的许多虚拟枚举器,以获取所需的特定枚举器.
这导致以下问题:
int?int?enum?Kei*_*son 10
如何设置int范围之外的枚举常量的值?
你没有.
C99标准要求用于定义枚举常量值的表达式具有可表示为的值
int.
是的,C11标准没有改变任何一个.
但是,枚举类型可以由实现定义为与任何整数类型兼容,包括那些值范围之外的整数类型
int.
也正确.
这意味着虽然您无法在a的范围之外显式设置枚举常量
int的值,但是int如果实现将枚举类型与具有范围的整数类型兼容,则枚举常量的值可以在a的范围之外.在...之外int.
这是不正确的,但我认为你发现标准中的措辞存在缺陷.(更新:我认为这不是一个弱点;见下文).你引用了6.7.2.2:
定义枚举常量值的表达式应为整数常量表达式,其值可表示为 int.
这似乎只适用于由显式表达式定义的值,而不是像这样的情况:
enum too_big {
big = INT_MAX,
even_bigger
};
Run Code Online (Sandbox Code Playgroud)
但这实际上并不起作用,因为它even_bigger被声明为类型的常量int,显然不具有该值INT_MAX + 1.
我强烈怀疑的意图是,上述声明是非法的(违反约束); 应该重新编写6.7.2.2以使其更清晰.(更新:我现在认为它已经足够清楚了;见下文.)
gcc的作者似乎同意我的看法:
$ cat c.c
#include <limits.h>
enum huge {
big = INT_MAX,
even_bigger
};
$ gcc -c c.c
c.c:4:5: error: overflow in enumeration values
Run Code Online (Sandbox Code Playgroud)
因此,即使您的解释是正确的,您也不太可能编写和使用依赖于它的代码.
解决方法是使用整数(无论如何,枚举类型或多或少都是伪装的整数).一个const整数对象不是一个常量表达式,不幸的是,所以你可能不得不求助于使用预处理:
typedef long long huge_t;
#define big ((huge_t)INT_MAX)
#define even_bigger (big + 1)
Run Code Online (Sandbox Code Playgroud)
这假设long long宽度大于int,可能但不保证(如果至少为64位int,则long long可以是相同的大小int).
你的问题1和2的答案是否定的; 你不能在范围之外定义一个负数或正数的枚举常量int.
至于你的问题3,C11标准的5.2.4.1节(大致)说,编译器必须在单个枚举中支持至少 1023个枚举常量.大多数编译器实际上没有强加固定限制,但是在任何情况下,所有常量都必须具有范围内的值INT_MIN.. INT_MAX,这对你没有多大帮助.(同一类型中的多个枚举常量可以具有相同的值.)
(翻译限制要求实际上比这更复杂.编译器必须支持至少一个程序,其中包含所有枚举列表的至少一个实例.这是一个相当无用的要求,如上所述.目的是最简单的方法满足标准要求是为了避免施加任何固定限制.)
更新:
我在comp.std.c Usenet新闻组中提出了这个问题.Tim Rentsch在讨论中提出了一个很好的观点,我现在认为:
enum too_big {
big = INT_MAX,
even_bigger
};
Run Code Online (Sandbox Code Playgroud)
是违反约束,需要编译器诊断.
我担心的是禁止在以下范围之外的明确值的措辞int:
定义枚举常量值的表达式应为整数常量表达式,其值可表示为 int.
不适用,因为没有涉及(显式)表达.但6.7.7.2p3说:
具有no =的每个后续枚举器将其枚举常量定义为通过将1添加到先前枚举常量的值而获得的常量表达式的值.
(重点补充).所以有一个表达式,其值必须可以表示为int; 它只是没有出现在源代码中.我对此并不是很满意,但我会说意图非常明确.
这是关于comp.std.c 的讨论.