C 如何将枚举常量的值设置在int范围之外?
C99标准要求用于定义枚举常量值的表达式具有可表示为C 如何将枚举常量的值设置在int范围之外?,c,enums,enumeration,c99,language-lawyer,C,Enums,Enumeration,C99,Language Lawyer,C99标准要求用于定义枚举常量值的表达式具有可表示为int的值 在C99标准第6.7.2.2节第2段中: 定义枚举常量值的表达式应为整数 具有可表示为int的值的常量表达式 但是,实现可以将枚举类型定义为与任何整数类型兼容,包括那些值范围超出int的类型 在C99标准第6.7.2.2节第2段中: 每个枚举类型应与字符、有符号整数类型或 无符号整数类型 这意味着,虽然不能显式地将枚举常量的值设置在int范围之外,但如果实现将枚举类型定义为与范围在int之外的整数类型兼容,则枚举常量的值可以在int
int
的值
在C99标准第6.7.2.2节第2段中:
定义枚举常量值的表达式应为整数
具有可表示为int的值的常量表达式
但是,实现可以将枚举类型定义为与任何整数类型兼容,包括那些值范围超出int
的类型
在C99标准第6.7.2.2节第2段中:
每个枚举类型应与字符、有符号整数类型或
无符号整数类型
这意味着,虽然不能显式地将枚举常量的值设置在int
范围之外,但如果实现将枚举类型定义为与范围在int
之外的整数类型兼容,则枚举常量的值可以在int
范围之外
现在我知道了一种获取枚举常量
int
集合范围之外的特定值的方法:伪枚举数
这得益于C99标准第6.7.2.2节第3段:
=
的枚举数定义其
枚举常量作为常量表达式的值。…
没有
=
将其枚举常量定义为通过以下方式获得的常量表达式的值:
将1添加到上一个枚举常量的值
不幸的是,这只适用于大于INT_MAX
的正值,因为每个后续枚举数的值只递增。另一个警告是需要创建可能多个伪枚举数,以获取所需的特定枚举数
这导致了以下问题:
int
范围之外的负值int
范围之外的正值设置为枚举常量枚举中可能声明的枚举数设置了限制
int
是的,C11标准没有改变这一切
但是,枚举类型可以由要执行的实现定义
与任何整数类型兼容,包括范围为
int
之外的值
也对
这意味着,虽然无法显式设置
枚举常量在int
范围之外,即
如果
实现将枚举类型定义为与
范围超出int
的整数类型
这是不正确的,但我认为你已经发现了标准中措辞的弱点。(更新:我不认为这是一个真正的弱点;见下文)。您引用了6.7.2.2:
定义枚举常量值的表达式应为
是一个整型常量表达式,其值可表示为
int
这似乎只适用于由显式表达式定义的值,而不适用于以下情况:
enum too_big {
big = INT_MAX,
even_bigger
};
但这实际上不起作用,因为甚至更大的被声明为int
类型的常量,它显然不能具有值int\u 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
这假设long-long
比int
宽,这很可能但不能保证(int
和long-long
的大小可能相同,如果int
至少为64位)
你的问题1和2的答案是否定的;不能定义超出int
范围的枚举常量,无论是负值还是正值
至于问题3,C11标准的第5.2.4.1节(大致上)说,编译器必须在单个枚举中至少支持1023个枚举常量。大多数编译器实际上并没有施加固定的限制,但在任何情况下,所有常量的值都必须在INT\u MIN
范围内INT_MAX
,所以这对您没有多大好处。(同一类型中的多个枚举常量可以具有相同的值。)
(翻译限制要求实际上比这更复杂。编译器必须至少支持一个程序,该程序至少包含一个枚举限制列表的实例。正如所述,这是一个相当无用的要求。其目的是,满足标准给出的要求的最简单方法是避免强加任何限制。)固定限制。)
更新:
我在comp.std.c Usenet新闻组上提出了这个问题。Tim Rentsch在讨论中提出了一个很好的观点,我现在认为:
enum too_big {
big = INT_MAX,
even_bigger
};
是约束冲突,需要编译器诊断
我担心的是禁止显式值超出int
范围的措辞:
表达
typedef long long huge_t;
#define big ((huge_t)INT_MAX)
#define even_bigger (big + 1)
enum too_big {
big = INT_MAX,
even_bigger
};
enum T { X = INT_MAX, BIGG}