4

Why does a zero-sized array force a struct to be zero sized when an otherwise empty struct has a size of 1, and why does inheriting from a non-zero-sized struct cause the struct to be inflated to the size of the base type?

Compiling via GCC 5.3.0, in case any answer depends on the c++ spec.

#include <iostream>

struct a {};
struct b { int x[0]; };
struct c : a{ int x[0]; };
struct d : b{ int x[0]; };

int main()
{
    std::cout << sizeof(a) << std::endl; // 1
    std::cout << sizeof(b) << std::endl; // 0
    std::cout << sizeof(c) << std::endl; // 4
    std::cout << sizeof(d) << std::endl; // 0
} 
Tyler Stoney
  • 418
  • 3
  • 13
  • 6
    _"...answer depends on the c++ spec..."_ - `int x[0];` is an extension - best to ask your compiler vendor - see _"...which evaluates to a value greater than zero..."_ https://en.cppreference.com/w/cpp/language/array – Richard Critten Apr 21 '21 at 20:56
  • The reason that the derived class has to be as big as the base class is that the base class members are the first members of the derived class - that's why if you cast the derived class into a base class the object is sliced so that only the base class members are available. – Jerry Jeremiah Apr 21 '21 at 20:57
  • code compiled under GCC with a few useful compiler options turned on: https://godbolt.org/z/zdKK6n3E1 English translation is roughly "Don't do this." – user4581301 Apr 21 '21 at 20:58
  • I had to change the array sizes to `1`, because `0` failed to compile on my machine. The sizes I got were: 1, 4, 4 and 8. – Eljay Apr 21 '21 at 21:02
  • think about `int x[0]`: in an array the indices go from 0 to N-1 but in this case N=0 so the indices start at 0 and go up to -1?! Even in C if you have a struct with a 0 size array you cannot create an object of it - you have to dynamically create memory for the struct. According to https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html `Declaring zero-length arrays in other contexts, including as interior members of structure objects ..., is discouraged. Accessing elements of zero-length arrays declared in such contexts is undefined and may be diagnosed.` – Jerry Jeremiah Apr 21 '21 at 21:02
  • Interestingly GCC 5.3 doesn't give most of these warnings: https://godbolt.org/z/GnPeqncoc Let's hear it for progress. – user4581301 Apr 21 '21 at 21:03
  • Here are other answers that say basically the same thing: https://stackoverflow.com/questions/9722632/what-happens-if-i-define-a-0-size-array-in-c-c https://stackoverflow.com/questions/295027/array-of-zero-length – Jerry Jeremiah Apr 21 '21 at 21:05

1 Answers1

3

The ISO C++ standard does not recognize the possibility of a "zero-sized array". That should give you a compile error on a strictly-conforming implementation. While yes, there are a lot of permissive implementations that allow it, their behavior is not governed by the C++ standard.

Similarly, the ISO C++ standard does not permit any type T for which sizeof(T) is zero. Ever. Again, some implementation may do this, but it is not conforming with the standard.

So why it happens depends on the compiler and the expectations of the writer of that code. Zero-sized arrays are generally a C-ism (though C forbids them too, but the C-ism may predate C89), so while it might be meaningful in C code, how they interact with C++ features is really up to the compiler.

The reason c might have a size while d does not could be because a is a normal C++ struct that follows the C++ standard and b isn't. So c::a (the base class of c) still has to follow the normal rules of C++ to some degree, while d::b is completely up to whatever the compiler wants to make of it.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982