【问题标题】:What is the size of an empty struct in C?C中空结构的大小是多少?
【发布时间】:2009-10-26 18:21:00
【问题描述】:

据我所知,它是零,但似乎有点混乱here

我已经用 gcc 编译器对其进行了测试,它给了我零作为输出。我知道在 C++ 中,空类的大小是 1。如果我在这里遗漏了什么,请告诉我。

【问题讨论】:

  • @Ben S 感谢您重新格式化问题!
  • C++ 标准(至少 C++03)没有声明 sizeof 应用于空类/结构的结果等于 1。

标签: c compiler-construction


【解决方案1】:

C 中的结构不能为空,因为语法禁止它。此外,如果结构没有命名成员,则存在语义约束使行为未定义:

struct-or-union-specifier:
  struct-or-union identifieropt { struct-declaration-list }
  struct-or-union identifier

struct-or-union:
  struct
  union

struct-declaration-list:
  struct-declaration
  struct-declaration-list struct-declaration

struct-declaration:
  specifier-qualifier-list struct-declarator-list ;

/* type-specifier or qualifier required here! */
specifier-qualifier-list:
  type-specifier specifier-qualifier-listopt
  type-qualifier specifier-qualifier-listopt

struct-declarator-list:
  struct-declarator
  struct-declarator-list , struct-declarator

struct-declarator:
  declarator
  declaratoropt : constant-expression

如果你写

struct identifier { };

它会给你一个诊断信息,因为你违反了句法规则。如果你写

struct identifier { int : 0; };

然后你有一个没有命名成员的非空结构,从而使行为未定义,并且不需要诊断:

如果 struct-declaration-list 不包含命名成员,则行为未定义。

注意以下是不允许的,因为灵活的数组成员不能是第一个成员:

struct identifier { type ident[]; };

【讨论】:

  • 但以下代码与 gcc 编译器完美配合,并且打印为零 ` struct abc { }; printf("空结构的大小 %d\n", sizeof(struct abc));'
  • -ansi -pedantic 编译给出“main.c:2: warning: struct has no members”
  • 空结构是 GCC 扩展。
  • 我不相信 C 标准说如果您违反了仅包含在 BNF 中的规则,则需要进行诊断。在大多数情况下,仅当包含“约束”条款的“应”或“不应”被违反时,才需要进行诊断。在 C++ 中,情况略有不同(它指定“可诊断规则集 包含本国际标准中的所有句法和语义规则......”
  • C99 至少说“如果预处理翻译单元或翻译单元包含违反任何语法规则或约束,则符合要求的实现应产生至少一个诊断消息(以实现定义的方式标识), ...”
【解决方案2】:

C 语法不允许 struct 的内容为空 - 必须至少有一个未命名的位域或命名成员(就语法而言 - 我不确定一个仅包含未命名位域的结构在其他情况下有效)。

Support for empty structs in C are an extension in GCC.

在 C++ 中,明确允许空结构/类成员规范,但大小定义为 1 - 除非作为空基优化的一部分,允许编译器使空基类在派生中不占用空间类。

【讨论】:

    【解决方案3】:

    在 C99 中:“如果 struct-declaration-list 不包含命名成员,则行为未定义。”

    语法实际上并不允许这样做,尽管我没有看到任何说需要诊断的东西,这使它几乎回到了“未定义行为”阵营。

    【讨论】:

    • “No named members”是指未命名bitfleld的具体情况(见上面litb的回复)。一个普通的空结构(根本没有成员)是违反约束的,而不是 UB。
    • 我刚刚重读了一遍,没有看到这样的限制。我正在查看§6.7.2.1。我看到的约束在第 2 到第 4 段。第 2 段说唯一允许的不完整类型是灵活数组。第 3 段说位域的宽度可以为零且没有名称,或者名称和宽度介于 1 和基础对象的大小之间。第 4 段说位域的底层类型应该是 _Bool、unsigned 或 int(或其他由实现定义的)。
    • 这是语法规则违规,需要诊断消息。
    • 如果它违反了语法规则,那么它肯定需要诊断——但我看不到任何说 BNF 构成语法规则一部分的东西。在大多数情况下,它们被视为非规范性的(例如,附录 A 包含整个 BNF,但被特别标记为“信息性”)。
    • @Jerry,“语法”部分中的规则(如 C99 中的 6.7.2.1/1)当然是语法规则。附录 A 仅总结了第 6 条中已经给出的所有规则,因此提供了信息。
    【解决方案4】:

    在 VC 8 上,如果我们尝试获取空结构的 sizeof,则会出错,而在使用 gcc 的 linux 上,它会给出大小 1,因为它使用 gcc 扩展而不是 c 语言规范,这表示这是未定义的行为。

    struct node
    {
    // empty struct.
    };
    
    int main()
    {
    printf("%d", sizeof(struct node));
    return 0;
    }
    

    在 windows vc 2005 上它给出了编译错误 在带有 gcc 的 linux 上,它的大小为 1,因为 gcc 扩展 http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Empty-Structures.html#Empty-Structures (正如迈克尔·伯尔所指出的)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多