tags:

views:

1009

answers:

7

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?

+4  A: 

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

Michael Mrozek
This is wrong. See the comments by @AndreyT on the answer of @isbadawi.
wilhelmtell
Just because GCC allows it doesn't make it legal C/C++.
John Dibling
+23  A: 

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.

Michael Burr
In C is it not permitted or is it undefined?
TheJuice
@TheJuice: the grammar requires that there be something in the struct definition, but I think you might be able to get away (grammar-wise) with just a semi-colon (I'm not sure about that - reading BNF isn't one of my strong suits). However, if you don't have anything with a name inside the struct definition, then you're in undefined behavior territory (which really buys you nothing - you can't count on it to do anything sensible).
Michael Burr
@Michael Burr: Actually, the grammar itself already prohibits empty structs. An empty struct in C is immediately a syntax error, not a UB. The remark about "no named members - UB" is there to close a different loophole. You can declare `struct { int : 1 }` (i.e. an unnamed bitfield) to formally satisfy the grammar requirements. To outlaw things like that there's that extra remark there.
AndreyT
Thanks for expanding on your answer.
TheJuice
@Andrey: `struct { char : 0; };` is even more empty. (GCC at least make your example the size of an `int`.) — hey, I tried this, and GCC *does* create a struct of size 0! G++ makes it size 1.
Potatoswatter
@Potatoswatter: (While in aggressively pedantic mood...) In that case it should be `struct { int : 0; };`. C language does not allow bitfields of `char` type :)
AndreyT
@Andrey: I see, C99 §6.7.2.1/4 "A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type." Also, I just tested the `int:1` way and GCC and G++ do make it size 1. Sorry about that.
Potatoswatter
@Potatoswatter: OK, I should've said "C language does not guarantee support for bitfields of `char` type"
AndreyT
gcc does return 0 for a sizeof an empty struct;int main(){ printf("%i",sizeof(struct {})); }
flownt
A: 

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).

alvin
it is not a matter of opinion here. there is an authority that has a final say here -- the standard -- and the question is about what the standard says about `sizeof` being zero.
wilhelmtell
@wilhelmtell, common sense has the potential to override any standard.
Joshua
@Joshua: And your compiler has the potential to override your common sense. If you care at all about your code functioning across multiple compilers, your best bet is to forget what your common sense tells you and stick to the standard.
Dennis Zickefoose
@Joshua sometimes the standard committee makes what looks like bad decisions. Yes, I agree. But this decision is not one of those bad decisions, if we really want to descend to futile endless opinionated discussions. The reason `sizeof()` an empty `struct` is not zero is so the standard can guarantee no two distinct instantiations of an empty `struct` (or two distinct empty `structs`) share the same memory address. In particular, this guarantees calls to `operator new()` will return a valid, unique memory address (or else fail altogether).
wilhelmtell
@Joshua Now, if the discussion is about whether we should listen to the standard or not then it is a futility of a different kind. The kind where we can either agree we should follow the standard, agree to disagree, or agree we shouldn't follow the standard and expect a velociraptor to come by and spontaneously bite each of our limbs off. In fact, while we're at it, why don't we disagree about speaking a common language? Disagree about relying our rationale on a common logic, or have common ethics? Surely there are better ways to get progress and order. Or, who needs these anyway?
wilhelmtell
@Joshua: Huh? How exactly does common sense override the standard? Are you saying that as long as it is common sense that something should work, the compiler will magically do it, *even if it's illegal according to the language standard*? I'm sorry, but programming doesn't work like that. What the compiler actually *does* overrides common sense *every single time*. And what the compiler actually does is dictated by the language standard. Common sense has no say whatsoever in this or any other language behavior question.
jalf
I'm saying that ridicules things in the standard eventually get replaced by compiler vendors.
Joshua
+13  A: 

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.

AndreyT
reference or it didn't happen.
MK
@MK: The language standard is the refernce. There's no single place there. It all derives from such facts that any object type by definition has non-zero size in both C or in C++. The fact that you can't apply `sizeof` to incomplete types also plays a role. And so on.
AndreyT
So, in terms of votes, which question should stackoverflow rank higher: +8/-0 or +19/-11 ? One is controversial, the other is a consensus, nudge-nudge.
wilhelmtell
A: 

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

Natasha
+4  A: 

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.

bta
That logic is why C++ requires that sizeof never return 0. But according to Michael Burr's answer, an empty struct in C is undefined behavior. Which probably explains why gcc's implementation of empty structs violates all of your assumptions.
Dennis Zickefoose
@bta: What you said might apply to C++. In C an empty struct (as in your example) is simply a constraint violation, a syntax error. So formally the issue of "size of empty struct" does not even exist in C.
AndreyT
@AndreyT: I realize that an empty struct is invalid in C, I just wanted to show that even if you *could* do it, the definition of `sizeof` would still return non-zero.
bta
@bta Nicely worded. You should just add that C chose to solve this problem by disallowing empty structs altogether, while C++ chose to solve it by defining them to be of size of at least 1.
wilhelmtell
@bta: gcc choses to allow empty structs in C, and assigns them a size of zero.
Dennis Zickefoose
@Dennis: Hmm, that's an interesting choice on gcc's part. In any case, such behavior would seem to violate the C standard (as I read it), so definitely do not write code assuming this behavior.
bta
Objects are not always required to have a unique address: `int a[1]; assert(` or `struct T { int n; } obj; assert(` (for those examples, in fact, it's required that the have the same address).
Roger Pate
bta
The array example really does have two different objects (`sizeof(a) != sizeof(a[0])` as you pointed out too) and it's really the same case as the struct. If you said "every object of the same data type must have a unique address" in the answer, it would be an improvement.
Roger Pate
A: 

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;
}
nos
I could be reading things wrong, but I believe that VLAs in C must have sizes greater than zero. "If the size is an expression that is not an integer constant expression: ... otherwise, each time it is evaluated it shall have a value greater than zero."
Dennis Zickefoose
Could be, gcc however, yields 0 - so "it is possible" - though maybe it's not correct.
nos