繁体   English   中英

sizeof是否可以返回0(零)

[英]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中的此项

正如伊斯巴达维 提到的 ,空结构。 gcc还允许使用0大小的数组

int a[0];
sizeof(a);

编辑:看到MSDN链接后,我尝试在VS2005中使用空结构,并且sizeof确实返回1。我不确定这是否是VS错误,或者规范是否对这种事情有某种灵活性

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM