问题 此枚举声明是否符合标准?


因此,通常枚举用于将“常量整数”组声明为另一种类型,代表某种东西。例如。

enum Color {RED=0, BLUE, YELLOW};

这很清楚。但最近我在代码中遇到了以下内容。这是嵌入式系统的编译器。

enum State {DISABLED=0, ENABLED=!DISABLED};

它运作得很好。它表现为布尔类型。我的问题是,它(这种语法)是否符合ANSI标准?

如果它符合标准,那么为什么编译器会在内部定义像_Bool这样的布尔表示然后在 stdbool.h (对于C语言)他们这样做:

#define bool _Bool
... // here goes definitions of true and false

代替

enum bool {false=0, true=!false};

哪个更干净?


9938
2017-10-25 22:19


起源

符合ANSI标准?这是我一段时间没有听过的短语。 - Alan Stokes
@DawidPi C和C ++是不同的语言,像这样的微妙问题几乎从来没有得到同时涵盖两种语言的好答案。如果您真的想知道这两种语言,请将它们作为单独的问题提出。
@AlanStokes如果你对我在评论中特别说明的编辑有问题,那么在没有任何评论的情况下回复它似乎很粗鲁。我不想对此进行回滚战争,但就我而言,这个问题在其原始状态下过于宽泛,如果你要阻止尝试使其处于适当的状态,那么,我只会投票结束。 (这当然不是说它实际上最终会被关闭。)
@hvd这是否合理?我想知道两种语言,在这种情况下回复两者,非常相似。在你的提示之后我删除了C ++标志,但是在答案出现并且也覆盖了C ++的部分后,我恢复了C ++标志,因为答案不合适。那我该怎么办? - DawidPi
@DawidPi是的,这是一个混乱的情况,如果你在一个问两个问题,并且实际上得到了解决你的两个问题的答案,那么保持原样是有道理的。实际上C ++的相关细节并不是我希望放在其中的当前答案的一部分,但它们对C没有任何意义......


答案:


是的,声明在C和C ++中完全有效且可移植。

在C和C ++中,这个:

enum State {DISABLED=0, ENABLED=!DISABLED};

完全等同于:

enum State {DISABLED=0, ENABLED=1};

对此:

enum State {DISABLED, ENABLED};

但出于不同的原因。

在C,一元 ! 运算符产生类型的结果 int,有价值的 0 (如果操作数不等于 0) 要么 1 (如果操作数等于 0)。 !x 相当于 x == 0。 (当用作条件时,任何非零值都被视为true,但是 ! 和 == 运营商,总是产生精确的结果 0 要么 1。)枚举常量总是类型 int;如果指定了值,则将其转换为 int 如有必要。

(C添加类型 _Bool 在1999年的标准中,但是所有产生逻辑“布尔”值的运算符仍然会产生类型的结果 int。)

在C ++中,一元的结果 ! 运算符是类型 bool。结果是 false 要么 true C的地方 ! 运营商会屈服 0 要么 1, 分别。与在C中一样,如果指定了值,则根据需要进行转换;该 bool 值 false 和 true 转换成 0 和 1, 分别。

在C中,枚举常量始终是类型 int。在C ++中,在这种情况下,它们是枚举类型 enum State

在同一类型声明中引用较早的枚举常量是合法的。每个枚举常量在声明后变为可见。

至于像这样的东西:

enum bool { false = 0, true = !false );

更清楚

enum bool { false = 0, true = 1 };

(在C中;它在C ++中是非法的),我恭敬地不同意。常数 1 对任何熟悉C的人都非常清楚。将其重写为 !false 没用实际上,何时 <stdbool.h> 不可用(这些日子很少见),我用过:

typedef enum { false, true } bool;

这个事实 false 和 true 将给出他们正确的值是恕我直言,足够明显。

至于为什么C99没有使用 enum 这样的定义,我怀疑是因为每个枚举类型都与某些实现定义的整数类型兼容。 (对于gcc,它通常是 unsigned int 要么 int。)委员会希望 _Bool 转换等级低于任何其他整数类型的独特类型。 (他们无法做到 bool 关键字而不破坏现有代码。)


3
2017-10-26 04:22





是的,这符合标准。

!DISABLED 是有效的 不变 表达式,这是一个必需的 enum 值。

enum State {DISABLED=0, ENABLED= (!DISABLED)};
//                               ^^^^^^^^^^^

在那里 DISABLED 引用时,编译器知道它的值,因此它可以计算从它派生的表达式的值,即 !DISABLED。这是一种奇特的写作方式 ENABLED=1


6
2017-10-25 22:25



一个人只是写一个有正当理由吗? ENABLED = 1 (即使是 = 1 可能是多余的,除非你想让它“清楚”) - Jack
“这是一种奇特的写作方式 ENABLED=1 是不正确的。鉴于枚举实际上是一个'int'大小,并且'!DISABLED'并不意味着添加1而是'非0',这会直接打入代码,无论编译器看到'ENABLED' - user3629249
@ user3629249:什么? - Ry-♦
@ user3629249:就C而言: “逻辑否定运算符的结果!如果其操作数的值比较不等于0则为0;如果其操作数的值比较等于0则为1.结果的类型为int。表达式!E等价于(0 == E)“ (来自C11草案)。所以,是的,这是一种奇特的写作方式 ENABLED=1 在C.你似乎在谈论用“直接打入代码”的宏,它们与枚举完全不同。 - Ry-♦
@ user3629249:C11没有改变含义 !value。 - Keith Thompson


根据C标准(6.2.1标识符范围)

每个枚举常量的范围都在...之后开始   枚举器列表中定义的枚举器的外观

这在C ++中是有效的(3.3.2声明点)

5普查员的声明点紧随其后   枚举器定义。[例如:

const int x = 12;
{ enum { x = x }; }

这里,枚举器x用常量的值初始化   x,即12.-末端示例]

因此,您可以在枚举中的下一个枚举数的定义中使用已定义的枚举器。

至于C型 _Bool 然后它出现在C 99中。在此标准之前,在C中使用了显式常量或枚举。

定义这样的枚举是没有意义的

enum bool {false=0, true!=false};

因为类型 _Bool 已经有两个值0和1。


3
2017-10-25 22:23