sizeof 可以返回 0(零)

发布于 2024-08-29 06:12:51 字数 62 浏览 8 评论 0原文

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

Is it possible for the sizeof operator to ever return 0 (zero) in C or C++? If it is possible, is it correct from a standards point of view?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

爱要勇敢去追 2024-09-05 06:12:51

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

在 C 中,不允许使用空结构,除非通过扩展(或编译器中的缺陷)。

这是语法(要求大括号内有某些内容)以及 6.7.2.1/7“结构和联合说明符”中的这句话的结果:“如果结构声明列表不包含命名成员,则行为是未定义的”。

如果允许零大小的结构,那么它就是语言扩展(或编译器中的缺陷)。例如,在 GCC 中,扩展记录在 “没有成员的结构”,其中表示:

GCC 允许 C 结构没有成员:

 结构空 {
 };

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

In C++ an empty class or struct has a sizeof at least 1 by definition. From the C++ standard, 9/3 "Classes": "Complete objects and member subobjects of class type shall have nonzero size."

In C an empty struct is not permitted, except by extension (or a flaw in the compiler).

This is a consequence of the grammar (which requires that there be something inside the braces) along with this sentence from 6.7.2.1/7 "Structure and union specifiers": "If the struct-declaration-list contains no named members, the behavior is undefined".

If a zero-sized structure is permitted, then it's a language extension (or a flaw in the compiler). For example, in GCC the extension is documented in "Structures with No Members", which says:

GCC permits a C structure to have no members:

 struct empty {
 };

The structure will have size zero. In C++, empty structures are part of the language. G++ treats empty structures as if they had a single member of type char.

花海 2024-09-05 06:12:51

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

sizeof never returns 0 in C and in C++. Every time you see sizeof evaluating to 0 it is a bug/glitch/extension of a specific compiler that has nothing to do with the language.

余生再见 2024-09-05 06:12:51

C 中的每个对象都必须有一个唯一的地址。换句话说,一个地址只能容纳一个给定类型的对象(为了使指针解除引用起作用)。话虽这么说,请考虑一个“空”结构:

struct emptyStruct {};

更具体地说,考虑一个由它们组成的数组:

struct emptyStruct array[10];
struct emptyStruct* ptr = &array[0];

如果对象确实是空的(即,如果 sizeof(structemptyStruct) == 0),那么ptr++ ==> (void*)ptr + sizeof(structemptyStruct) ==> ptr,这没有意义。 *ptr 将引用哪个对象,ptr[0] 还是 ptr[1]

即使一个结构体没有内容,编译器也应该将其视为一个字节长度,以维护“一个地址,一个对象”的原则。

C 语言规范(A7.4.8 节)将此要求表述为

当应用于结构或联合时,
结果(sizeof 运算符)
是对象中的字节数,
包括制作所需的任何填充
对象平铺一个数组

添加到“空”对象中才能使其在数组中工作,因此对于任何有效的 sizeof() 必须返回至少为 1 的值输入。

编辑:
C 规范的 A8.3 节将没有成员列表的结构称为“不完整类型”,并且 sizeof 的定义明确指出(添加了强调):

运算符(sizeof)可能不是
应用于函数的操作数

类型,或不完整类型,或
位域。

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

编辑:另请参阅此条目 Bjarne Stroustrup 的常见问题解答。

Every object in C must have a unique address. Worded another way, an address must hold no more than one object of a given type (in order for pointer dereferencing to work). That being said, consider an 'empty' struct:

struct emptyStruct {};

and, more specifically, an array of them:

struct emptyStruct array[10];
struct emptyStruct* ptr = &array[0];

If the objects were indeed empty (that is, if sizeof(struct emptyStruct) == 0), then ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr, which doesn't make sense. Which object would *ptr then refer to, ptr[0] or ptr[1]?

Even if a structure has no contents, the compiler should treat it as if it is one byte in length in order to maintain the "one address, one object" principle.

The C language specification (section A7.4.8) words this requirement as

when applied to a structure or union,
the result (of the sizeof operator)
is the number of bytes in the object,
including any padding required to make
the object tile an array

Since a padding byte must be added to an "empty" object in order for it to work in an array, sizeof() must therefore return a value of at least 1 for any valid input.

Edit:
Section A8.3 of the C spec calls a struct without a list of members an incomplete type, and the definition of sizeof specifically states (with emphasis added):

The operator (sizeof) may not be
applied to an operand
of function
type, or of incomplete type, or to a
bit-field.

That would imply that using sizeof on an empty struct would be equally as invalid as using it on a data type that has not been defined. If your compiler allows the use of empty structs, be aware that using sizeof on them is not allowed as per the C spec. If your compiler allows you to do this anyway, understand that this is non-standard behavior that will not work on all compilers; do not rely on this behavior.

Edit: See also this entry in Bjarne Stroustrup's FAQ.

扶醉桌前 2024-09-05 06:12:51

空结构,如 isbadawi 提及。 gcc还允许0大小的数组

int a[0];
sizeof(a);

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

Empty structs, as isbadawi mentions. Also gcc allows arrays of 0 size:

int a[0];
sizeof(a);

EDIT: After seeing the MSDN link, I tried the empty struct in VS2005 and sizeof did return 1. I'm not sure if that's a VS bug or if the spec is somehow flexible about that sort of thing

何其悲哀 2024-09-05 06:12:51

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

但这可能会导致问题。
当定义此类结构的数组时,

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

这会使它们失去其身份。

我想这并不能直接回答你的问题,无论是否可能。
好吧,这可能取决于编译器。 (正如迈克尔上面的回答所述)。

in my view, it is better that sizeof returns 0 for a structure of size 0 (in the spirit of c).
but then the programmer has to be careful when he takes the sizeof an empty struct.

but it may cause a problem.
when array of such structures is defined, then

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

which makes them lose their identities.

i guess this doesnt directly answer your question, whether it is possible or not.
well that may be possible depending on the compiler. (as said in Michael's answer above).

把昨日还给我 2024-09-05 06:12:51
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 的位域表示没有其他位域将被打包到放置前一个位字段(如果有)的单元中。”

typedef struct {
  int : 0;
} x;

x x1;
x x2;

Under MSVC 2010 (/Za /Wall):

sizeof(x) == 4
&x1 != &x2

Under GCC (-ansi -pedantic -Wall) :

sizeof(x) == 0
&x1 != &x2

i.e. Even though under GCC it has zero size, instances of the struct have distinct addresses.

ANSI C (C89 and C99 - I haven't looked at C++) says "It shall be possible to express the address of each individual byte of an object uniquely." This seems ambiguous in the case of a zero-sized object, since it arguably has no bytes.

Edit: "A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field. As a special case of this, a bit-field with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bit-field, if any, was placed."

黯淡〆 2024-09-05 06:12:51

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

I think it never returns 0 in c , no empty structs is allowed

吃素的狼 2024-09-05 06:12:51

这是一个测试,其中 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;
}

Here's a test, where sizeof yields 0

#include <stdio.h>

void func(int i)
{
        int vla[i];
        printf ("%u\n",(unsigned)sizeof vla);
}


int main(void)
{

        func(0);
        return 0;
}
羁绊已千年 2024-09-05 06:12:51

如果你有这个:

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

g++ -ansi 返回 sizeof(Bar) == 0。英特尔编译器。

然而,这不能用 gcc 编译。我推断它是一个 C++ 扩展。

If you have this :

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

g++ -ansi returns sizeof(Bar) == 0. As does the clang & intel compiler.

However, this does not compile with gcc. I deduce it's a C++ extension.

弥繁 2024-09-05 06:12:51
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
struct Empty {
} em;

struct Zero {
    Empty a[0];
} zr;

printf("em=%d\n", sizeof(em));
printf("zr=%d\n", sizeof(zr));

Result:

em=1
zr=0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文