这个结构怎么会有 sizeof == 0 呢?
How can this structure have sizeof == 0?
有一个旧的 post 要求 sizeof
会 return 0
的结构。有一些来自高声誉用户的高分答案说,按照标准,任何类型或变量都不能有 sizeof 0。我 100% 同意这一点。
然而 this new answer 提出了这个解决方案:
struct ZeroMemory {
int *a[0];
};
我正要对它投反对票并发表评论,但在这里度过的时间教会了我去检查我 100% 确定的事情。所以...令我惊讶的是 gcc
和 clang
显示相同的结果:sizeof(ZeroMemory) == 0
。更重要的是,变量的大小是 0
:
ZeroMemory z{};
static_assert(sizeof(z) == 0); // Awkward...
哇……?
这怎么可能?
正如 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
行为。但至少我们知道这不是标准的...
在 C++ 中,大小为零的数组是非法的。
ISO/IEC 14882:2003 8.3.4/1:
[..] If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero. The constant expression specifies the bound of (number of elements in) the array. If the value of the constant expression is N
, the array has N
elements numbered 0
to N-1
, and the type of the identifier of D
is “derived-declarator-type-list array of N
T”. [..]
g++ 需要 -pedantic
标志以在大小为零的数组上发出警告。
零长度数组是 GCC 和 Clang 的扩展。将 sizeof
应用于零长度数组 evaluates to zero.
C++ class(空)不能有大小 0
,但请注意 class ZeroMemory
不是空的。它有一个命名成员,大小为 0
,应用 sizeof
将 return 为零。
在 C 标准化之前,只要代码从不尝试从另一个指针中减去一个指向零大小类型的指针,许多编译器就可以毫不费力地处理零大小类型。这些类型很有用,支持它们比禁止它们更容易、成本更低。然而,其他编译器决定禁止此类类型,并且某些静态断言代码可能依赖于这样一个事实,即如果代码试图创建大小为零的数组,它们会发出尖叫声。该标准的作者面临着一个选择:
允许编译器静默接受零大小的数组声明,即使
在此类声明的目的是触发
诊断和中止编译,并要求所有编译器接受
这样的声明(虽然不一定是默默地)产生零 -
大小的对象。
允许编译器静默接受零大小的数组声明,即使
在此类声明的目的是触发
诊断和中止编译,并允许编译器遇到这样的
声明中止编译或在空闲时继续编译。
如果代码声明了一个
零大小的数组,但随后允许实现中止
编译或继续它(用他们认为合适的任何语义)在
他们的闲暇。
标准的作者选择了#3。因此,标准 "extension" 认为零大小的数组声明,即使在标准禁止它们之前此类构造已得到广泛支持。
C++ 标准允许空对象的存在,但为了允许空对象的地址可用作标记,它要求它们的最小大小为 1。对于没有成员的对象因此,大小为 0 将违反标准。但是,如果一个对象包含大小为零的成员,则 C++ 标准除了包含此类声明的程序必须触发诊断这一事实外,不会对其处理方式施加任何要求。由于大多数使用此类声明的代码都希望生成的对象的大小为零,因此对于接收此类代码的编译器而言,最有用的行为就是以这种方式处理它们。
有一个旧的 post 要求 sizeof
会 return 0
的结构。有一些来自高声誉用户的高分答案说,按照标准,任何类型或变量都不能有 sizeof 0。我 100% 同意这一点。
然而 this new answer 提出了这个解决方案:
struct ZeroMemory {
int *a[0];
};
我正要对它投反对票并发表评论,但在这里度过的时间教会了我去检查我 100% 确定的事情。所以...令我惊讶的是 gcc
和 clang
显示相同的结果:sizeof(ZeroMemory) == 0
。更重要的是,变量的大小是 0
:
ZeroMemory z{};
static_assert(sizeof(z) == 0); // Awkward...
哇……?
这怎么可能?
正如 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
行为。但至少我们知道这不是标准的...
在 C++ 中,大小为零的数组是非法的。
ISO/IEC 14882:2003 8.3.4/1:
[..] If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero. The constant expression specifies the bound of (number of elements in) the array. If the value of the constant expression is
N
, the array hasN
elements numbered0
toN-1
, and the type of the identifier ofD
is “derived-declarator-type-list array ofN
T”. [..]
g++ 需要 -pedantic
标志以在大小为零的数组上发出警告。
零长度数组是 GCC 和 Clang 的扩展。将 sizeof
应用于零长度数组 evaluates to zero.
C++ class(空)不能有大小 0
,但请注意 class ZeroMemory
不是空的。它有一个命名成员,大小为 0
,应用 sizeof
将 return 为零。
在 C 标准化之前,只要代码从不尝试从另一个指针中减去一个指向零大小类型的指针,许多编译器就可以毫不费力地处理零大小类型。这些类型很有用,支持它们比禁止它们更容易、成本更低。然而,其他编译器决定禁止此类类型,并且某些静态断言代码可能依赖于这样一个事实,即如果代码试图创建大小为零的数组,它们会发出尖叫声。该标准的作者面临着一个选择:
允许编译器静默接受零大小的数组声明,即使 在此类声明的目的是触发 诊断和中止编译,并要求所有编译器接受 这样的声明(虽然不一定是默默地)产生零 - 大小的对象。
允许编译器静默接受零大小的数组声明,即使 在此类声明的目的是触发 诊断和中止编译,并允许编译器遇到这样的 声明中止编译或在空闲时继续编译。
如果代码声明了一个 零大小的数组,但随后允许实现中止 编译或继续它(用他们认为合适的任何语义)在 他们的闲暇。
标准的作者选择了#3。因此,标准 "extension" 认为零大小的数组声明,即使在标准禁止它们之前此类构造已得到广泛支持。
C++ 标准允许空对象的存在,但为了允许空对象的地址可用作标记,它要求它们的最小大小为 1。对于没有成员的对象因此,大小为 0 将违反标准。但是,如果一个对象包含大小为零的成员,则 C++ 标准除了包含此类声明的程序必须触发诊断这一事实外,不会对其处理方式施加任何要求。由于大多数使用此类声明的代码都希望生成的对象的大小为零,因此对于接收此类代码的编译器而言,最有用的行为就是以这种方式处理它们。