【问题标题】:Are an incomplete enum and a complete enum compatible types?不完整枚举和完整枚举兼容类型吗?
【发布时间】:2021-01-13 10:44:04
【问题描述】:

在一个翻译单元中,我有一个完全定义的枚举:

typedef enum E { A, B, C } ET;

在另一种情况下,我对这个枚举只有一个不完整的定义:

typedef enum E ET;

我想知道这两种类型是否兼容。

兼容类型的定义在this page 中有描述,但对我来说似乎很模糊。当两个枚举是完整类型时有一个解释,但我不确定如果一个是而不是另一个会发生什么。

下面这句话应该怎么理解?

一个是枚举类型,另一个是枚举的底层类型

这是否意味着两种类型都兼容?

【问题讨论】:

  • 但是..兼容类型在这里无关。两个文件中的enum EET相同的类型
  • 我不确定第一个 TU 中的 ET 是否与第二个 TU 中的 ET 相同,这是我的问题。确实,如果它们是同一类型,我同意它们是兼容的。
  • 好的。你会如何使用ET在第二个?
  • @KamilCuk 在第二个 TU 中,ET 不是直接使用的,而是一个以ET 为参数的函数指针。此函数指针位于我想在两个翻译单元中操作的结构中。如果不清楚,如果您愿意,我可以发布一个虚拟示例。

标签: c enums


【解决方案1】:

你的问题没有意义。 C 没有不完整的 enums(与不完整的数组或联合或结构不同),即使许多编译器在您不请求 -pedantic 一致性检查时支持它们。

https://gcc.godbolt.org/z/vTv85v

【讨论】:

    【解决方案2】:

    哎呀,incomplete enum 是一个编译器扩展,类似于gcc Incomplete-Enums。其余答案假定“不完整枚举”遵循与不完整结构和联合相同的规则。

    不完整枚举和完整枚举兼容类型吗?

    是的(如果它们的名称相同)。

    这是否意味着两种类型都兼容?

    是的。从您链接到的 cppreference:

    类型 T 和 U 是兼容的,如果

    • 它们是相同的类型(相同的名称或由 typedef 引入的别名)

    即。 ET 是两个单元中 enum E 的别名 - ET 在两个单元中都兼容。后来:

    • 它们都是结构/联合/枚举类型,并且
      • (C99)如果一个用标签声明,另一个也必须用相同的标签声明。
      • 如果两者都是完成类型,blabla

    enum E 具有相同的标签 - E - 所以它们也是兼容的。并且第二个TU的enum E不完整,所以这里不适用附加点。

    我们还要提一下C11 6.2.7 兼容类型和复合类型的原话:

    1. 如果类型相同,则两种类型具有兼容的类型。
      用于确定两种类型是否兼容的附加规则在 6.7.2 中描述了类型说明符,在 6.7.3 中描述了类型限定符,在 6.7.6 中描述了声明符。
      此外,如果它们的标签和成员满足以下要求,则在单独的翻译单元中声明的两种结构、联合或枚举类型是兼容的:如果一个用标签声明,另一个应该用相同的标签声明。
      如果两者都在各自翻译单元内的任何地方完成,则 以下附加要求适用:
      它们的成员之间应该是一一对应的,这样每一对对应的成员都被声明为兼容的类型;
      如果对中的一个成员使用对齐说明符声明,则另一个成员使用等效的对齐说明符声明;
      如果该对中的一个成员声明了一个名称,则另一个成员声明为相同的名称。
      对于两个结构,相应的成员应以相同的顺序声明。对于两个结构或联合,对应的位域应具有相同的宽度。
      对于两个枚举,对应的成员应具有相同的值。

    下面这句话应该怎么理解?

    一个是枚举类型,另一个是枚举的底层类型

    每个enum 都有一个“基础类型”——它并不是真正的enum作为一种类型,它实际上是intchar 或其他实现定义的类型。让我们引用 C11 6.7.2.2 枚举说明符:

    1. 每个枚举类型都应与 char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,但应该能够表示枚举的所有成员的值。枚举类型在终止枚举器声明列表的 } 之后是不完整的,然后完成。

    第一句话比较明确。这个“真实类型”编译器的选择是依赖的——大多数时候它只是一个unsigned intint。请参阅您的编译器文档,例如 gcc implementation define behavior 4.9 Structures, Unions, Enumerations, and Bit-Fields:

    与每个枚举类型兼容的整数类型(C90 6.5.2.2, C99 和 C11 6.7.2.2)。

    通常,如果没有负值,则类型为 unsigned int 枚举,否则为 int。如果指定了 -fshort-enums,则如果 有负值它是有符号字符的第一个,短和 int 可以表示所有值,否则是第一个 unsigned char, unsigned short 和 unsigned int 可以代表所有 值。

    在某些目标上,-fshort-enums 是默认值;这是由 ABI 决定的。

    这点one is an enumerated type and the other is that enumeration's underlying type 是关于unsigned intenum E 可能是兼容的类型,所以你不妨使用unsigned int

    【讨论】:

      【解决方案3】:

      这条记录

      typedef enum E ET;
      

      不正确。

      根据 C 标准(6.7.2.3 标签)

      3 形式的类型说明符

      enum identifier
      

      没有枚举器列表只能出现在它的类型之后 指定完成。

      因此,如果前面有枚举E 的完整声明,那么有关兼容性的问题就可以毫无问题地解决。否则编译器会发出错误信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多