1

TL;DR:假设,给定enum NAME {...};,这与执行期间enum NAME n相同吗?即使它被声明为 ,也可以int n像? 原因:我真的想将类型用于返回标志,作为关于位操作的“关闭”类型。nsigned intenum NAMEenum

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

我搜索了标准(这里的草图)并查看了其他相关问题,但没有提到任何可疑(并希望)是 to 的“无声促销” enum NAME xsigned int x即使标识符具有那种类型。这让我相信,enum当分配一个不是成员的值时,行为方式是依赖于实现的。我要求,部分是为了确认或否认这一说法。

4

2 回答 2

2

C 2018 6.7.2.2 4 说:

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

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

然而,它实际上是一个整数类型,所以FLAGS f = F1 | F2;可以工作:该FLAGS类型必须能够表示它的值F1F2,所以无论使用什么类型都FLAGS必须包含F1和 的所有位F2,所以它包含 的所有位F1 | F2

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

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

于 2021-03-13T11:44:52.820 回答
0

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

声明为枚举常量的标识符具有类型int

enum NAME x您对to的提升的想法signed int x并不是真的,因为它是type的标识符 。该是您用于定义标识符的类型,并且它被提升为.NAMEint xint

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

编辑

enum一些编译器对和之间的区别非常认真int,特别是如果他们可以选择将位宽减小到尽可能小。例如,我在工作项目中使用的那个会自动插入检查每个值的使用enum与定义的值。此外,IIRC,它拒绝所有隐式转换,我们需要显式转换,类似于:

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

但这是这种特殊野兽的延伸,带有特定的安全选项......

于 2021-03-13T11:24:09.600 回答