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?
Solution 1:
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:
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.
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.
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.
Solution 2:
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...