我可以在 C17 中将 `enum` 变量视为 `int` 吗?

Can I treat an `enum` variable as an `int` in C17?

TL;DR:假设 enum NAME {...}; 在执行期间 enum NAME nint n 相同是否正确? n 是否可以像 signed int 一样操作,即使它被声明为 enum NAME?原因:我真的想对 return 标志使用 enum 类型,作为 'closed' 相对于位操作的类型。

例如:设typedef enum FLAGS { F1 = 0x00000001, F2 = 0x00000002, F3 = 0x00000004 } FLAGS ; 然后,FLAGS f = F1 | F2;3 分配给 f,不抛出相关错误或警告。这个和许多其他编译器允许的使用场景,例如 f++,让我觉得我可以合法地将 f 当作 signed int。使用的编译器:MSVC'19、16.9.1,设置为“C17 (2018) Standard (/std:c17)”;

我搜索了标准(草图 here)并查看了其他相关问题,但没有提及怀疑(并希望)成为 enum NAME x 的“无声提升” signed int x,即使标识符具有该类型。这让我相信 enum 在分配一个非成员的值时的行为方式 依赖于实现 。我问,部分是为了确认或否认这一说法。

这在您链接的 PDF 的第 6.4.4.3 章中:

An identifier declared as an enumeration constant has type int.

您关于将 enum NAME x 提升为 signed int x 的想法是不正确的,因为它是 identifier NAME输入 intvalue x 是你用来定义标识符的类型,它被提升为 int.

此外,整数提升发生在整数运算中。

编辑

一些编译器非常重视 enumint 之间的区别,尤其是当它们可以选择将位宽减小到尽可能小的时候。例如,我在工作项目中使用的那个,会根据定义的值自动插入检查 eachenum 值的使用情况。此外,IIRC,它拒绝所有隐式转换,我们需要显式转换,类似于:

FLAGS f = (FLAGS)((int)F1 | (int)F2);

但这是这种特殊的野兽的扩展,具有特定的安全选项...

C 2018 6.7.2.2 4 说:

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration…

“我可以在 C17 中将 enum 变量视为 int 吗?”的答案不是,因为具有枚举类型的对象实际上可能是 char 或不同于 int.

的其他整数类型

然而,它实际上是一个整数类型,所以 FLAGS f = F1 | F2; 可以工作: FLAGS 类型必须能够表示它的值 F1F2,所以用于 FLAGS 的任何类型都必须包含 F1F2 的所有位,因此它包含 F1 | F2.

的所有位

从技术上讲,您可以通过操作位来构造陷阱表示,因此不能保证类型在位操作下是封闭的。例如,如果 C 实现对 32 位 int 使用二进制补码,但保留位模式 1000…0000 作为陷阱表示,则 INT_MIN & -2 将是陷阱表示。 (对于 231−1,INT_MIN 将具有位模式 1000…0001,而 -2 将具有模式 1111…1110。)在其整数类型中没有陷阱表示的 C 实现中不会发生这种情况。

我们可能会质疑两种类型(枚举及其实现定义的整数类型)兼容的事实是否意味着我们可以将一种用作另一种。如果两种类型相同(6.2.7 1),则它们是兼容的,并且唯一可以使类型兼容但不相同的东西涉及限定符(如 const),这不是问题或涉及其他属性与简单整数类型无关的(例如数组维度)。