【问题标题】:Why can enum values have large (>int) values?为什么枚举值可以具有大 (>int) 值?
【发布时间】:2020-01-30 04:03:45
【问题描述】:

在我定义了这样的枚举之后:

typedef enum { x = 1ULL<<40 } e;

似乎表达式“x”的计算结果为 1UL

但是,C11 6.4.4.3 说“声明为枚举常量的标识符具有 int 类型。”

顺便说一句,这可以节省我的时间,因为我想要枚举值 > 1如何;编写不符合标准的代码我有点紧张。

我试过这段代码:

int main() {
        printf("%zu %zu %lx\n", sizeof(e), sizeof(x), x);
        return 0;
}

gcc -std=c11 -Wall(gcc 8.3.1,linux x86_64)编译,输出:8 8 10000000000

如果我将 %lx 更改为 %llx,我会收到一个编译警告和相同的输出,这表明 x 是长尺寸的。

根据我对规范的阅读,我预计会出现编译警告并输出 4 4 0

【问题讨论】:

  • 还有“每个枚举类型应与 char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的”c17dr § 6.7.2.2 4 AFAIK,宽的类型是可以的,但不是1ULL&lt;&lt;40。嗯
  • 请注意,我违反了 §6.7.2.2 2,它表示枚举常量shall 具有可表示为int 的值。所以根据规范,我的代码是无效的 C。也许这允许他们在不违背规范的情况下扩展语言?
  • 我不会依赖此代码来工作,而是会找到另一个解决方案。

标签: c enums


【解决方案1】:

编译器扩展。例如,用叮当声:

$ CFLAGS=-Weverything make example && ./example
cc -Weverything    example.c   -o example
example.c:3:16: warning: ISO C restricts enumerator values to range of 'int'
      (1099511627776 is too large) [-Wpedantic]
typedef enum { x = 1ULL<<40 } e;
               ^   ~~~~~~~~
1 warning generated.
8 8 10000000000

使用 gcc:

$ CFLAGS='-Wall -pedantic' make example && ./example
cc -Wall -pedantic    example.c   -o example
example.c:3:20: warning: ISO C restricts enumerator values to range of ‘int’ [-Wpedantic]
 typedef enum { x = 1ULL<<40 } e;
                    ^~~~
8 8 10000000000

【讨论】:

  • 这些警告很好,但在我看来,clang 和 gcc 都产生了不正确的行为;规范确实说 sizeof(x) 应该等于 4,而不是 8。他们如何摆脱这个?是否有一些我缺少的 gcc 标志会给我输出4 4 0?或者他们是否可以声称 sizeof 可能是 8,因为某处存在某种未定义的行为?
  • @ErikCarstensen 规范没有说任何类型的大小都应该等于 4。此外,规范说如果程序违反约束,那么编译器应该发出诊断,它确实做到了. (因此,规范没有定义此类程序的行为)。您可以使用诸如-pedantic-errors-Werror 等编译器标志来阻止生成可执行文件
  • 从技术上讲,我认为这将是一个变体(它不是标准 C),而不是扩展。如果标准说类型是int,而实现中的类型不是int,那么实现不符合C标准。 (我们可以编写一个严格符合的程序来检测差异。)
  • 6.7.2.2 描述了其他可能的类型,所以谁知道呢。
  • @M.M 回答了我的问题。 @EricPostpischil,我不明白如何编写一个检测差异的符合程序,因为 §6.7.2.2 2 说枚举常量应具有可表示为 int 的值。
猜你喜欢
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
相关资源
最近更新 更多