是 enum { a } e = 1; 有效的?

Pav*_*kin 25 c enums language-lawyer

一个简单的问题: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>
Run Code Online (Sandbox Code Playgroud)

kod*_*der 31

来自6.7.2.2中的C18标准:

每个枚举类型应与 char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,但应能够表示枚举的所有成员的值。

所以“是”enum { a } e = 1;是有效的。e是“整数”类型,因此它可以采用 value 1。不作为枚举值出现这一事实1没有问题。枚举成员只为一些可能的值提供方便的标识符。

  • 即使它是“允许的”,也是不好的风格,应该避免。 (7认同)
  • 不过,这在旗帜中很常见。你不会说出每种组合的名称。 (4认同)
  • “*枚举成员只为一些可能的值提供方便的标识符*”——根据语言语义,是的,但这通常不是程序员的预期使用模型。使用“枚举”的程序员需要记住他们的心智模型与实际语言语义之间的脱节。 (3认同)

dfr*_*fri 6

在 C 语言中有效

这在 C 中有效,例如202x 工作草案

6.7.2.2/4每个枚举类型应与char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,但应能够表示枚举所有成员的值

特别是由于“兼容类型”的要求:

6.2.7/1如果两个类型的类型相同,则它们具有兼容类型。附加规则 [...]


... C++14 及更早版本/C++17 及更高版本中的实现定义和可能的未指定/未定义行为

虽然超出了本问答的范围(C 标签,而不是 C++),但值得注意的是,这不适用于 C++,其中没有固定基础类型的“C 风格”无作用域枚举与 C 存在细微差别。有关C++案例的详细信息,请参见以下Q&A:

  • 该问题始终被标记为 C,因此这里对 C++ 行为的讨论并不是特别相关。我建议发布一个新的自我回答问题,该问题与此问题基本相同,但针对 C++。(你可以链接到这个问题并询问“这就是它在 C 中的作用,那么 C++ 呢?”) (7认同)

Adr*_*ica 5

我在这个 C11 标准草案(就“约束”而言)中找不到任何禁止分配给像您这样的类型的参考(并且另一个答案enum中引用的 C18 标准使用基本相同的措辞)。

\n

然而,C11 草案在附件 I \xe2\x80\x93 常见警告中确实提供了这一点:

\n
\n

1 \xc2\xa0\xc2\xa0\xc2\xa0 实现可能会在许多\n情况下生成警告,但这些情况均未指定为此国际\n标准的一部分。以下是一些较常见的情况。

\n2
\n\xe2\x80\xa6
\n\xc2\xa0\xc2\xa0\xc2\xa0\xe2\x80\x94\xc2\xa0\xc2\xa0\xc2\xa0 一个值被赋予一个对象枚举类型,而不是通过分配作为该类型成员的枚举常量、具有相同类型的枚举对象、或返回相同枚举类型的函数的值 (6.7.2.2) 。

\n
\n

但是,建议的警告同样适用于像 这样的赋值enum { a } e = 0;,其中RHS 的对应于有效的枚举常量,但它实际上既不是该类型的枚举常量,也不是该枚举类型的对象。

\n