零大小结构体

13

我注意到使用GCC 4.6编译时,sizeof(Foo)为0,而sizeof(Bar)为1。由于在空结构中添加了一个空数组,因此其大小变为0。我原以为两个结构的大小必须相同,现在不太明白发生了什么。

struct Foo
{
    char x[];
};

struct Bar {};

1
很奇怪,sizeof永远不可能是_0_... - K-ballo
@Tudor:灵活数组,那是编译器扩展吗? - K-ballo
2
@K-ballo 不,自C99以来就已经成为标准了。但是一个具有柔性数组成员的结构体必须有多个命名成员。 - Daniel Fischer
7
根据gcc扩展文档,“柔性数组成员具有不完整类型,因此不能使用sizeof运算符。由于零长度数组的原始实现的怪癖,sizeof的结果为零。” - pb2q
2
gcc 4.2 在这里报告了一个编译器错误:_error: 灵活数组成员在除此之外是空的结构体_,与扩展文档中的描述一致。 - pb2q
显示剩余3条评论
3个回答

17
根据C标准第6.7.2.1(8)条款,不允许使用任何没有命名成员的结构声明。如果没有直接或通过匿名结构或匿名联合体包含任何命名成员,则行为未定义。在该部分的第18段中,对于具有多个命名成员的结构的最后一个元素可采用不完整数组类型,这称为"flexible array member"。 在大多数情况下,会忽略灵活的数组成员。特别是,结构体的大小好像省略了灵活的数组成员一样,但可能比省略更多地包含尾部填充。(强调我的) C++不允许使用灵活数组成员,因此该代码也无效。由于这不是有效的代码,因此对于它们报告的值,sizeof没有意义。

1

sizeof 运算符即使对于一个空类也不会产生 0。

正如您可以在 这里的 MSDN 上看到的那样。

此外,MSDN 还声明:

sizeof 运算符不能与以下操作数一起使用:

  • 函数。(但是,sizeof 可以应用于指向函数的指针。)
  • 位域。
  • 未定义的类。
  • 类型 void。
  • 动态分配的数组。
  • 外部数组。
  • 不完整类型。
  • 不完整类型的括号名称。

1

C和C++不允许零大小的对象。

gcc支持它们作为扩展。如果您使用正确的选项进行编译,例如

gcc -std=c99 -pedantic -Wall -Wextra

gcc 至少会警告您有关它们的信息;g++ 也有类似的选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接