这个结构如何具有sizeof == 0?

时间:2017-11-17 14:14:56

标签: c++ language-lawyer sizeof

有一篇旧帖子要求updateSegmentRequestInfo()将返回sizeof的构造。高信誉用户有一些高分答案说,按标准,没有类型或变量可以有0的大小。我同意100%。

但是this new answer提出了这个解决方案:

0

我正打算投票并对其发表评论,但是在这里度过的时间教会我检查我100%肯定的事情。所以......令我惊讶的是,struct ZeroMemory { int *a[0]; }; gcc显示了相同的结果:clang。更重要的是,变量的大小为sizeof(ZeroMemory) == 0

0

Whaaaat ...?

Godbolt link

这怎么可能?

4 个答案:

答案 0 :(得分:50)

在C标准化之前,只要代码从未尝试从另一个指针中减去一个指向零大小类型的指针,许多编译器就可以毫无困难地处理零大小的类型。这些类型很有用,支持它们比禁止它们更容易和更便宜。然而,其他编译器决定禁止这些类型,并且一些静态断言代码可能依赖于如果代码试图创建零大小的数组它们会发出尖叫的事实。该标准的作者面临着一个选择:

  1. 允许编译器静默接受零大小的数组声明,甚至 如果此类声明的目的是触发a 诊断和中止编译,并要求所有编译器都接受 产生零的声明(虽然不一定是默默地) 大小的物体。

  2. 允许编译器静默接受零大小的数组声明,甚至 如果此类声明的目的是触发a 诊断和中止编译,并允许编译器遇到这样的 宣布要么中止汇编,要么继续闲暇。

  3. 如果代码声明了a,则要求实现发出诊断 零大小的数组,但随后允许实现中止 编译或继续它(用他们认为合适的语义) 他们的闲暇。

  4. 标准的作者选择了#3。因此,标准“扩展”认为零大小的数组声明,即使这些结构在标准禁止之前得到广泛支持。

    C ++标准允许存在空对象,但为了允许空对象的地址可用作标记,它要求它们的最小大小为1.对于没有成员的对象因此,大小为0将违反标准。但是,如果一个对象包含零大小的成员,那么除了包含这种声明的程序必须触发诊断这一事实外,C ++标准对它的处理方式没有任何要求。由于大多数使用此类声明的代码都希望生成的对象的大小为零,因此接收此类代码的编译器最有用的行为就是以这种方式对待它们。

答案 1 :(得分:40)

正如Jarod42所指出的,零大小的数组不是标准的C ++,而是GCC和Clang扩展。

添加-pedantic会产生此警告:

5 : <source>:5:12: warning: zero size arrays are an extension [-Wzero-length-array]
    int *a[0];
           ^

我始终忘记std=c++XX(而非std=gnu++XX)并未禁用所有扩展程序。

这仍然无法解释sizeof行为。但至少我们知道它不是标准......

答案 2 :(得分:18)

在C ++中,零大小的数组是非法的。

ISO / IEC 14882:2003 8.3.4 / 1:

  

[..]如果常量表达式(5.19)存在,它应是一个整数常量表达式,其值应大于零。常量表达式指定数组中的(元素数)的边界。如果常量表达式的值为N,则数组具有编号为N0的{​​{1}}个元素,N-1的标识符类型为“ {em> derived-declarator-type-list D T“数组。 [..]

g ++需要N标志来对零大小的数组发出警告。

答案 3 :(得分:4)

零长度数组是GCC和Clang的扩展。将sizeof应用于零长度数组evaluates to zero

C ++类(空)的大小不能为0,但请注意,类ZeroMemory不为空。它有一个名为0的成员,申请sizeof将返回零。