Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can this structure have sizeof == 0?

There is an old post asking for a construct for which sizeof would return 0. There are some high score answers from high reputation users saying that by the standard no type or variable can have sizeof 0. And I agree 100% with that.

However there is this new answer which presents this solution:

struct ZeroMemory {     int *a[0]; }; 

I was just about to down-vote and comment on it, but time spent here taught me to check even the things that I am 100% sure on. So... to my surprise both gcc and clang show the same results: sizeof(ZeroMemory) == 0. Even more, sizeof a variable is 0:

ZeroMemory z{}; static_assert(sizeof(z) == 0); // Awkward... 

Whaaaat...?

Godbolt link

How is this possible?

like image 429
bolov Avatar asked Nov 17 '17 14:11

bolov


People also ask

Can sizeof ever return 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.

How can the size of a structure be determined?

In C language, sizeof() operator is used to calculate the size of structure, variables, pointers or data types, data types could be pre-defined or user-defined. Using the sizeof() operator we can calculate the size of the structure straightforward to pass it as a parameter.

Can you use sizeof on a struct?

The sizeof for a struct is not always equal to the sum of sizeof of each individual member. This is because of the padding added by the compiler to avoid alignment issues. Padding is only added when a structure member is followed by a member with a larger size or at the end of the structure.

Why sizeof empty struct is 1?

C++ The C++ standard does not permit objects (or classes) of size 0. This is because that would make it possible for two distinct objects to have the same memory location. This is the reason behind the concept that even an empty class and structure must have a size of at least 1.


2 Answers

Before C was standardized, many compilers would have had no difficulty handling zero-size types as long as code never tried to subtract one pointer to a zero-size type from another. Such types were useful, and supporting them was easier and cheaper than forbidding them. Other compilers decided to forbid such types, however, and some static-assertion code may have relied upon the fact that they would squawk if code tried to create a zero-sized array. The authors of the Standard were faced with a choice:

  1. Allow compilers to silently accept zero-sized array declarations, even in cases where the purpose of such declarations would be to trigger a diagnostic and abort compilation, and require that all compilers accept such declarations (though not necessarily silently) as producing zero- sized objects.

  2. Allow compilers to silently accept zero-sized array declarations, even in cases where the purpose of such declarations would be to trigger a diagnostic and abort compilation, and allow compilers encountering such declarations to either abort compilation or continue it at their leisure.

  3. Require that implementations issue a diagnostic if code declares a zero-sized array, but then allow implementations to either abort compilation or continue it (with whatever semantics they see fit) at their leisure.

The authors of the Standard opted for #3. Consequently, zero-sized array declarations are regarded by the Standard "extension", even though such constructs were widely supported before the Standard forbade them.

The C++ Standard allows for the existence of empty objects, but in an effort to allow the addresses of empty objects to be usable as tokens it mandates that they have a minimum size of 1. For an object that has no members to have a size of 0 would thus violate the Standard. If an object contains zero-sized members, however, the C++ Standard imposes no requirements about how it is processed beyond the fact that a program containing such a declaration must trigger a diagnostic. Since most code that uses such declarations expects the resulting objects to have a size of zero, the most useful behavior for compilers receiving such code is to treat them that way.

like image 147
supercat Avatar answered Sep 20 '22 03:09

supercat


As pointed out by Jarod42 zero size arrays are not standard C++, but GCC and Clang extensions.

Adding -pedantic produces this warning:

5 : <source>:5:12: warning: zero size arrays are an extension [-Wzero-length-array]     int *a[0];            ^ 

I always forget that std=c++XX (instead of std=gnu++XX) doesn't disable all extensions.

This still doesn't explain the sizeof behavior. But at least we know it's not standard...

like image 28
bolov Avatar answered Sep 24 '22 03:09

bolov