Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将枚举常量的值设置在int范围之外?_C_Enums_Enumeration_C99_Language Lawyer - Fatal编程技术网

C 如何将枚举常量的值设置在int范围之外?

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

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节第3段:

=
的枚举数定义其 枚举常量作为常量表达式的值。

没有
=
将其枚举常量定义为通过以下方式获得的常量表达式的值: 将1添加到上一个枚举常量的值

不幸的是,这只适用于大于
INT_MAX
正值,因为每个后续枚举数的值只递增。另一个警告是需要创建可能多个伪枚举数,以获取所需的特定枚举数


这导致了以下问题:

  • 有没有办法将枚举常量的值设置为
    int
    范围之外的负值
  • 是否有更好的方法将
    int
    范围之外的正值设置为枚举常量
  • 关于我的虚拟枚举器攻击,C99标准是否对单个
    枚举中可能声明的枚举数设置了限制
  • 如何将枚举常量的值设置在int范围之外?

    你没有

    C99标准要求用于定义值的表达式 枚举常量的值可表示为
    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}