sizeof可以返回0(零)

时间:2010-04-13 18:15:13

标签: c++ c sizeof

sizeof运算符是否有可能在C或C ++中返回0(零)?如果有可能,从标准的角度来看是否正确?

10 个答案:

答案 0 :(得分:40)

在C ++中,根据定义,空类或结构的sizeof至少为1。从C ++标准来看,9/3“Classes”:“类类型的完整对象和成员子对象应具有非零大小。”

在C中,除了扩展名(或编译器中的缺陷)之外,不允许使用空结构。

这是语法的结果(要求括号内有东西)以及6.7.2.1/7“结构和联合说明符”中的这句话:“如果struct-declaration-list不包含命名成员,行为未定义“。

如果允许零大小的结构,则它是语言扩展(或编译器中的缺陷)。例如,在GCC中,扩展名记录在"Structures with No Members"中,其中包含:

  

GCC允许C结构没有成员:

 struct empty {
 };
     

结构的大小为零。在C ++中,空结构是语言的一部分。 G ++将空结构视为具有char类型的单个成员。

答案 1 :(得分:20)

sizeof永远不会在C和C ++中返回0。每当您看到sizeof评估为0时,它就是与该语言无关的特定编译器的错误/故障/扩展。

答案 2 :(得分:9)

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)可能不是   应用于函数的操作数   类型,或不完整类型,或者a   位字段。

这意味着在空结构上使用sizeof与在未定义的数据类型上使用它同样无效。如果您的编译器允许使用空结构,请注意,根据C规范,不允许在它们上使用sizeof。如果您的编译器允许您仍然执行此操作,请了解这是非标准行为,不适用于所有编译器;不要依赖这种行为。

编辑:另请参阅Bjarne Stroustrup常见问题解答中的this entry

答案 3 :(得分:5)

空结构,isbadawi mentions。 gcc还允许arrays of 0 size

int a[0];
sizeof(a);
编辑:在看到MSDN链接之后,我在VS2005中尝试了空结构,并且sizeof确实返回1.我不确定这是一个VS错误,还是规范在某种程度上是灵活的

答案 4 :(得分:2)

在我看来,对于大小为0的结构(在c的精神中),sizeof最好返回0。 但是程序员在获取空结构的大小时必须要小心。

但可能会导致问题。 当定义了这种结构的数组时,那么

& arr [1] ==& arr [2] ==& arr [0]

这使他们失去了自己的身份。

我想这不能直接回答你的问题,无论是否有可能。 好吧,这可能取决于编译器。 (正如Michael在上面的回答中所说的那样)。

答案 5 :(得分:1)

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的位字段表示不再进一步将位字段打包到放置前一位字段(如果有的话)的单元中。“

答案 6 :(得分:0)

我认为它永远不会在c中返回0,不允许空结构

答案 7 :(得分: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;
}

答案 8 :(得分:0)

如果你有这个:

struct Foo {}; 
struct Bar { Foo v[]; }

g++ -ansi返回sizeof(Bar)== 0。同样,clang&amp;英特尔编译器。

但是,这不能用gcc编译。我推断它是C ++扩展。

答案 9 :(得分:-1)

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