10

I have this situation which I cannot explain why it compiles:

#include <iostream>
using namespace std;

class X {
public:
    X() {cout << "in X constructor: " << endl;};
};

class Y {
public:
    Y() {cout << "in Y constructor" << endl;};
private:    
    X x[];
};

int main() {
    Y y;
    return 0;
}

I am defining a variable size array of X as a member of class Y. Defining X it is such a way outside the class would surely result in a compile error, but not within the class. What’s more, the constructor of X is never called.

So what is happening here?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Davor Josipovic
  • 5,296
  • 1
  • 39
  • 57
  • 2
    That's not a variable-length array, but a "flexible array". IIRC, in C, this allows a `malloc` trick, appending arbitrary amounts to a struct with a "nice" array-like interface. In C++, this is a GNU extension of g++ and clang++. See, e.g http://stackoverflow.com/q/246977/420683 – dyp Feb 24 '14 at 14:21
  • Whats the problem with that explanation: warning C4200: nonstandard extension used : zero-sized array in struct/union ? – knivil Feb 24 '14 at 14:24
  • @remyabel When compiling `int x[]` in `main()` I get compile error: `storage size of 'x' isn't known`. So I assume that `int x[0]` is a zero sized array of `int`. – Davor Josipovic Feb 24 '14 at 14:25
  • 5
    Overly lax compiler settings: `error: ISO C++ forbids zero-size array 'x' [-pedantic]` – juanchopanza Feb 24 '14 at 14:28

1 Answers1

13

C99, 6.7.2.1/16 (n1256)

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.

It is not a variable-length array. It isn't anything like a data member, more like an interface to tell the compiler you can access some memory via the name of the flexible array member.

/17

EXAMPLE After the declaration:

struct s { int n; double d[]; };

the structure struct s has a flexible array member d. A typical way to use this is:

int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

and assuming that the call to malloc succeeds, the object pointed to by p behaves, for most purposes, as if p had been declared as:

struct { int n; double d[m]; } *p;

This is not allowed in C++11, but accepted by g++ and clang++ as an extension. As the number of elements isn't known to the constructor of the struct (for C++), the constructor cannot initialize those elements (automatically).

dyp
  • 38,334
  • 13
  • 112
  • 177
  • I am compiling the above code with `g++` and `-std=c++11` option. – Davor Josipovic Feb 24 '14 at 14:28
  • @davor *"warning: ISO C++ forbids zero-size array 'x' [-Wpedantic]"* – dyp Feb 24 '14 at 14:29
  • @remyabel See the example in /17; /16 talks about an *incomplete type*. The zero-length array IIRC was a g++ extension before C99 standardized the flexible array member. – dyp Feb 24 '14 at 14:33
  • Yeah, I see no reason C++ shouldn't be able to initialize an array of incomplete type, but they seem to get hung up after converting the `[]` to `[0]` (which is a bit of nonsense really). – Potatoswatter Feb 24 '14 at 14:44
  • @Potatoswatter Huh? How would you initialize an array of incomplete type? Either the number of elements is not known, or the element type is incomplete (or both). The conversion from `[]` to `[0]` probably follows the [old g++ extension](http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html#Zero-Length). – dyp Feb 24 '14 at 14:48
  • @dyp Sorry, but I still don’t get it completely. All this is about structs and C. How does all this translate to classes which are not part of C? – Davor Josipovic Feb 24 '14 at 14:52
  • @davor It doesn't translate at all! There are no flexible array members in C++. However, g++ and clang++ allow them as an extension. `struct`s and `class`es are pretty much the same thing in C++. – dyp Feb 24 '14 at 14:54