2

The C++ standard requires that all types are at least 1 byte in size even though a struct has no members. i.e.

struct x { };

but

sizeof(x) == 1

Same is with arrays. It is not standard conforming to declare zero length arrays (in C, C++ and C99).

int x[0];   // not allowed in C, C++ and C99 standards

So why is that? To me it seems like an uneccessary requirement, that actually introduces inconsistency.

I know that some compilers allow zero length arrays as an extention, and also that C99 allows a "zero" length array at the end of a structure, which is however more of a variable length array and only possible at the end of a struct.

So my question is: what is the rationale behind fobidding zero length arrays or requiring sizeof > 0 in the language standards?

Andreas H.
  • 5,557
  • 23
  • 32
  • I suspect because it would break the identity `sizeof(T[N]) == sizeof(T) * N`. – GManNickG Oct 18 '13 at 04:26
  • Doubly so because `new T[0]` is allowed, and this is different because there is no compile-time size information attached to the allocated array (you only get a pointer to the first element back). – GManNickG Oct 18 '13 at 04:27
  • why is sizeof(T[N]) == sizeof(T)*N ? I am not sure if I understand. Suppose int x[0]; then we had sizeof(x) == 0 and sizeof(x[0]) == sizeof(int). What would be wrong with that? – Andreas H. Oct 18 '13 at 04:43
  • @AndreasH.: when he said `sizeof(T[N])`, I think he meant that `T` was a type. `sizeof(x[0])` is the size of the component type of the array `x`, and is the same as `sizeof(x[1])`; `sizeof(int[0])` is an error. But suppose it wasn't an error: what would it be? It could not be 0 because 0-length objects are not allowed, but if it were not 0, then it would not be 0*sizeof(int), breaking the rule that sizeof(int[N]) is always N*sizeof(int). At least, that's my interpretation of G.'s point. – rici Oct 18 '13 at 05:15
  • possible duplicate of [Why is the size of an empty class in C++ not zero?](http://stackoverflow.com/questions/2362097/why-is-the-size-of-an-empty-class-in-c-not-zero). The standard requires that `&T[1] - &T[0] == 1` which is hard to accomplish if `T` had size zero. – Raymond Chen Oct 18 '13 at 06:04
  • @rici: the thing is that if one would allow zero size types (sizeof(T)==0) or zero size arrays (N=0) the formula sizeof(T[N]) == sizeof(T)*N is still valid. That is why I dont understand. – Andreas H. Oct 18 '13 at 12:29
  • @RaymondChen: regarding your second point: Well pointer arithmetic with zero size types would be undefined because it leads to 0/0. because (&T[1]-&T[0]) is just (adress1-adress2)/sizeof(T). But just because pointer arithmetic is undefined, it means that zero size types should be banned completely. Regarding the possible duplicate: I didnt find that in the first place, thanks for the link. – Andreas H. Oct 18 '13 at 12:32
  • @AndreasH.: If you allow zero-size types, you can no longer take the address of such an object. Suppose x is an array of zero-sized types. It's not possible that &x[0]==&x[1]. But &x[1] == &x[0] + sizeof *x. You might feel that this is not sufficient reason to ban zero-size types, but it has been debated several times by standards committees and they have always decided that the complications of zero-sized types of non-dynamic storage duration outweigh the benefits. – rici Oct 18 '13 at 13:43
  • @rici: Alright, I understand that if you want objects to be uniquely identifiable by their address (i.e. demand &x[0] != &x[1]), you cannot have zero sized types. Maybe I should have asked why one wants objects to be uniquely identifiable by their address. So probably Alec Teals answer explains that. – Andreas H. Oct 18 '13 at 16:11

2 Answers2

2

If something has a size >= 1, then no two "things" can have the same address, and thus the address of a thing is it's identity. (like "is" in Python, compared to ==, two strings can be equal but they may be different strings, they may have different identities)

I can also imagine (going back to C, which was created with functionality in mind before languages became so formal) that it makes pointer arithmetic make sense, stops weird memory allocations, allows pointers to be compared to check identity.... zero would be an annoying special case.

Alec Teal
  • 5,770
  • 3
  • 23
  • 50
-1

In my understanding, x[0] = has the same address with x. Therefore, the sizeof(x) always starts from 1, as x[0] is always initialized when you declare array x.

To answer your question, if we allowed zero length arrays in C, C++, the array would not actually be allocated at the point of definition. For example in Java, you declare an array

int [] a;

It is not allocated until you call

a = new int[10];
lightbringer
  • 835
  • 2
  • 12
  • 24
  • If x is an array of size n, &x[n] is a valid address, although it cannot be dereferenced. It's ok to use it for comparison, though, and it's also ok to increment p=&x[n-1]. Otherwise, standard loops would be impossible. So the fact that &x[0] is valid does not imply that x has one element. – rici Oct 18 '13 at 04:44
  • @lightbringer: I dont understand your point. yes x[0] has same address as x. also for zero length array. But in case of a zero length array it is out of bounds access but that is always possible in c. – Andreas H. Oct 18 '13 at 04:45