在一个翻译单元中,我有一个完全定义的枚举:
typedef enum E { A, B, C } ET;
在另一个例子中,我对这个枚举只有一个不完整的定义:
typedef enum E ET;
我想知道这两种类型是否兼容。
兼容类型的定义在本页中有描述,但对我来说似乎很模糊。当两个枚举是完整类型时,会有解释,但我不确定如果其中一个是而不是另一个,会发生什么。
下面的句子我应该理解什么?
一个是枚举类型,另一个是该枚举的底层类型
这是否意味着两种类型都兼容?
您的问题没有意义。C没有不完整的enum
(与不完整的数组、并集或结构不同),即使当您不请求-pedantic
一致性检查时,许多编译器都支持它们。
https://gcc.godbolt.org/z/vTv85v
没错,incomplete enum
是一个类似于gcc不完整枚举的编译器扩展。答案的其余部分假设";incolpete enum";遵循与不完全结构和联合相同的规则。
不完整枚举和完整枚举兼容类型吗?
是(如果它们的名称相同)。
这是否意味着两种类型都兼容?
是。从您链接到的cppreference:
如果,类型T和U是兼容的
- 它们是相同的类型(typedef引入的相同名称或别名)
Ie。ET
是两个单元中enum E
的别名——ET
在两个单元都兼容。后来:
- 它们都是结构/并集/枚举类型,并且
- (C99)如果一个用标记声明,那么另一个也必须用相同的标记声明
- 如果两者都是已完成类型,则blabla
在两个enum E
中都有相同的标记-E
,因此它们也是兼容的。第二个TU中的enum E
是不完整的,因此附加点在此不适用。
让我们还提到C11 6.2.7的原始版本兼容类型和复合类型:
- 如果两个类型的类型相同,则它们具有兼容的类型
6.7.2中对类型说明符、6.7.3中对类型限定符和6.7.6中对声明符描述了用于确定两个类型是否兼容的附加规则
此外,如果在单独的翻译单元中声明的两个结构、并集或枚举类型的标记和成员满足以下要求,则它们是兼容的:如果其中一个用标记声明,则另一个应用相同的标记声明
如果两者都在各自的翻译单位内的任何地方完成,则以下附加要求适用:
它们的成员之间应该有一对一的对应关系,这样每对对应的成员都用兼容的类型声明
如果用对齐说明符声明对中的一个成员,则用等效的对齐说明符声明另一个成员
如果用名称声明对中的一个成员,则用相同的名称声明另一个成员
对于两个结构,应按相同顺序声明相应的构件。对于两个结构或并集,相应的位字段应具有相同的宽度
对于两个枚举,对应的成员应具有相同的值
下面的句子我应该理解什么?
一个是枚举类型,另一个是该枚举的底层类型
每个CCD_;底层类型"-它并不是真正的enum
类型,它实际上是int
、char
或其他实现定义的类型。让我们引用C11 6.7.2.2枚举说明符:
- 每个枚举类型都应与char、带符号整数类型或无符号整数类型兼容。类型的选择由实现定义,但应能够表示枚举的所有成员的值。枚举类型在终止枚举器声明列表的}之后才是不完整的,然后才完成
第一句话相当明确。这个";实型";编译器的选择是依赖的——大多数时候它只是一个unsigned int
或int
。请参阅编译器文档,如gcc实现定义行为4.9结构、并集、枚举和位字段:
与每个枚举类型兼容的整数类型(C90 6.5.2.2,C99和C11 6.7.2.2)。
通常,如果中没有负值,则类型为unsigned int枚举,否则为int。如果指定了-fshort enums,则如果有负值-它是有符号字符中的第一个,short和int,它可以表示所有值,否则它是unsigned char、unsigned short和unsigned int可以表示值。
在某些目标上,-fshort枚举是默认值;这是由ABI决定的。
这一点one is an enumerated type and the other is that enumeration's underlying type
是关于unsigned int
和enum E
可能是兼容的类型,所以您还不如使用unsigned int
。
此记录
typedef enum E ET;
不正确。
根据C标准(6.7.2.3标签)
3 形式的类型说明符
enum identifier
没有枚举器列表的只能出现在它的类型之后指定已完成。
因此,如果前面有枚举E
的完整声明,那么关于兼容性的问题就迎刃而解了。否则,编译器将发出错误消息。