[英]Can sizeof return 0 (zero)
sizeof运算符是否有可能在C或C ++中返回0(零)? 如果有可能,从标准的角度来看是否正确?
在C ++中,根据定义,空类或结构的sizeof
至少为1。 从C ++标准的9/3“类”:“类类型的完整对象和成员子对象应具有非零大小。”
在C语言中,除非通过扩展名(或编译器中的缺陷),否则不允许使用空结构。
这是语法(要求花括号内有一些东西)以及6.7.2.1/7“结构和联合说明符”中的句子的结果:“如果struct-declaration-list不包含命名成员,则该行为未定义”。
如果允许使用零大小的结构,则它是语言的扩展(或编译器中的缺陷)。 例如,在GCC中,扩展名记录在“无成员的结构”中 ,内容为:
GCC允许C结构没有成员:
struct empty { };
该结构的大小为零。 在C ++中,空结构是该语言的一部分。 G ++将空结构视为具有
char
类型的单个成员。
在C和C ++中, sizeof
永远不会返回0
。 每次您看到sizeof
评估为0
它都是特定编译器的错误/故障/扩展,与该语言无关。
C中的每个对象都必须具有唯一的地址。 换句话说,一个地址最多只能容纳一个给定类型的对象(以使指针解除引用)。 话虽如此,请考虑一个“空”结构:
struct emptyStruct {};
更具体地说,是它们的数组:
struct emptyStruct array[10];
struct emptyStruct* ptr = &array[0];
如果对象确实为空(即,如果sizeof(struct emptyStruct) == 0
),则ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr
,这没有任何意义。 *ptr
然后会指向哪个对象ptr[0]
或ptr[1]
?
即使结构没有内容,编译器也应将其视为一个字节长,以保持“一个地址,一个对象”的原则。
C语言规范(第A7.4.8节)将此要求表述为
当应用于结构或联合时,(
sizeof
运算符的)结果是对象中的字节数,包括使对象平铺数组所需的任何填充
由于必须将填充字节添加到“空”对象才能使其在数组中工作,因此sizeof()
必须为任何有效输入返回至少为1的值。
编辑: C规范的A8.3节将没有成员列表的结构称为不完整的类型 ,并且sizeof
的定义专门声明了状态(并强调了):
运算符(sizeof) 可能不适用于函数类型, 不完整类型或位域的操作数。
这意味着在空结构上使用sizeof
在尚未定义的数据类型上使用sizeof
一样无效。 如果您的编译器允许使用空结构,请注意根据C规范,不允许在它们上使用sizeof
。 如果您的编译器仍然允许您执行此操作,请了解这是非标准行为,不适用于所有编译器。 不要依靠这种行为。
编辑:另请参阅Bjarne Stroustrup的FAQ中的此项 。
typedef struct {
int : 0;
} x;
x x1;
x x2;
在MSVC 2010(/ Za / Wall)下:
sizeof(x) == 4
&x1 != &x2
在GCC(-ansi -pedantic -Wall)下:
sizeof(x) == 0
&x1 != &x2
即,即使在GCC中它的大小为零,该结构的实例也具有不同的地址。
ANSI C(C89和C99-我没看过C ++)说:“应该可以唯一地表示对象的每个字节的地址。” 对于零大小的对象,这似乎是模棱两可的,因为可以说它没有字节。
编辑:“没有声明符,但只有一个冒号和一个宽度的位域声明表示未命名的位域。作为这种情况的特殊情况,宽度为0的位域表示没有其他位域将被打包到放置先前位字段(如果有)的单元中。”
在我看来,对于大小为0的结构(按照c的精神),最好sizeof返回0。 但是程序员在选择空结构的大小时必须要小心。
但这可能会引起问题。 当定义了此类结构的数组时,则
&arr [1] ==&arr [2] ==&arr [0]
这使他们失去了身份。
我想这并不能直接回答您的问题,无论是否可能。 可能取决于编译器。 (如上述迈克尔的回答所述)。
我认为它永远不会在c中返回0,不允许有空结构
这是一个测试,其中sizeof产生0
#include <stdio.h>
void func(int i)
{
int vla[i];
printf ("%u\n",(unsigned)sizeof vla);
}
int main(void)
{
func(0);
return 0;
}
如果您有这个:
struct Foo {};
struct Bar { Foo v[]; }
g++ -ansi
返回sizeof(Bar)==0。clang和intel编译器也是如此。
但是,这不能用gcc编译。 我推断这是C ++扩展。
struct Empty {
} em;
struct Zero {
Empty a[0];
} zr;
printf("em=%d\n", sizeof(em));
printf("zr=%d\n", sizeof(zr));
结果:
em=1
zr=0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.