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?
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
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
.
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).
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.
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.
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;
}