2

From ISO/IEC 14882:2003 8.3.4/1:

If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

Therefore the following should not compile:

#pragma once
class IAmAClass
{
public:
    IAmAClass();
    ~IAmAClass();

private:
    int somearray[0];    // Zero sized array
};

But it does. However, the following:

#pragma once
class IAmAClass
{
public:
    IAmAClass();
    ~IAmAClass();

private:
    int somearray[0];
    int var = 23;     // Added this expression
};

does not compile, with the following error (as what would be expected) (Visual C++)

error C2229: class 'IAmAClass' has an illegal zero-sized array

When the code is in a function, it, in accordance with the standard, will never compile.

So, why does the code behave in such a way in a header file, where the difference of the compilation passing or failing appears to be down to whether a statement proceeds the zero sized array declaration or not.

  • IIRC that's actually a C extension, allowing an arbitrary amount of data after the class data to be accessed. You'd need to manually allocate space for that data (via `malloc`). – dyp Jul 11 '14 at 21:37
  • @dyp, Flexible array members are valid as of C99. – chris Jul 11 '14 at 21:37
  • @chris I know, was a shorthand for "C construct allowed as an extension in C++" ;) – dyp Jul 11 '14 at 21:38
  • 1
    By the way @Ben this is not a zero-sized array but an *array of unknown bound*, an incomplete type. A zero-sized array would be `int somearray[0];` – dyp Jul 11 '14 at 21:41
  • @dyp I see. I edited the question to take this into account as the actual zero sized array behaves in the same way. –  Jul 11 '14 at 21:43
  • see: http://stackoverflow.com/a/296143/14065 – Martin York Jul 11 '14 at 21:48

2 Answers2

6

The keyword in "If the constant-expression (5.19) is present," is if. It's not, so the first version compiles.

However, such variant arrays are only permissible (and sane) when they are the last element in a struct or class, where it's expected that they'll use extra space allocated to the struct on a case-by-case basis.

If an unknown-length array were allowed before other elements, how would other code know where in memory to find those elements?

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • 2
    Data members of incomplete type are not allowed in C++. – dyp Jul 11 '14 at 21:38
  • g++ and others allow it, though. I'm not arguing the validity, just explaining what is *actually happening* in the OP's samples. – Paul Roub Jul 11 '14 at 21:47
  • The first sentence is not an explanation why it compiles. You cannot use the Standard (which disallows this program) to explain why this is allowed. – dyp Jul 11 '14 at 21:48
3

This is a Visual C++ language extension: Declaring Unsized Arrays in Member Lists. From the linked MSDN page:

Unsized arrays can be declared as the last data member in class member lists if the program is not compiled with the ANSI-compatibility option (/Za)


Edit: If the member has been declared as a zero-sized array (like int somearray[0];) instead of an array of unknown bounds (like int somearray[];), this is still a language extension, albeit a different one

A zero-sized array is legal only when the array is the last field in a struct or union and when the Microsoft extensions (/Ze) are enabled.


This extension is similar to C99's flexible array members C11/n1570 §6.7.2.1/18

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.

and /20 contains an example:

EXAMPLE 2    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;

[...]

dyp
  • 38,334
  • 13
  • 112
  • 177