12

For the C++ code fragment below:

class Foo {
    int a[]; // no error
};

int a[];     // error: storage size of 'a' isn't known

void bar() {
    int a[]; // error: storage size of 'a' isn't known
}

why isn't the member variable causing an error too? and what is the meaning of this member variable?

I'm using gcc version 3.4.5 (mingw-vista special) through CodeBlocks 8.02.

On Visual Studio Express 2008 - Microsoft(R) C/C++ Optimizing Compiler 15.00.30729.01 for 80x86, I got the following messages:

class Foo {
    int a[]; // warning C4200: nonstandard extension used : zero-sized array in struct/union - Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array
};

int a[];

void bar() {
    int a[]; // error C2133: 'a' : unknown size
}

Now, this needs some explaination too.

2
  • The caption mentions "static arrays". Where are these "static arrays" in your question? I don't see a single reference to any "static arrays". Commented Apr 27, 2010 at 0:11
  • I mean statically allocated arrays. Please feel free to edit the question if you see necessary. Thank you. Commented May 1, 2010 at 9:01

4 Answers 4

13

C++ language allows omitting array size only in non-defining declarations

extern int a[]; // non-defining declaration - OK in C++

int a[]; // definition - ERROR in C++

int a[5]; // definition - OK, size specified explicitly
int a[] = { 1, 2, 3 }; // definition - OK, size specified implicitly

Non-static class member decarations are always required to specify the array size

struct S {
  int a[]; // ERROR in C++
};

while static class member decarations can omit the size

struct S {
  static int a[]; // OK in C++
};

(the definition of the same member will, of course, have to specify the size).

Any deviations from this behavior can only be explaind by extended non-standard behavior of your compiler. Maybe you should specify some additional compiler settings to make it behave in more pedantic fashion.

Sign up to request clarification or add additional context in comments.

Comments

12

C99 supports something called a 'flexible' array member that is allowed to be the last member of a struct. When you dynamically allocate such a struct you can increase the amount requested from malloc() to provide for memory for the array.

Some compilers add this as an extension to C90 and/or C++.

So you can have code like the following:

struct foo_t {
    int x;
    char buf[];
};


void use_foo(size_t bufSize)
{
    struct foo_t* p = (foo_t*) malloc( sizeof( struct foo_t) + bufSize);
    
    int i;
    
    for (i = 0; i < bufSize; ++i) {
        p->buf[i] = i;
    }
}

You can't define a struct with a flexible array member directly (as a local or a global/static variable) as the compiler won't know how much memory to allocate for it.

I'm honestly not sure how you'd easily use such a thing with C++'s new operator - I think you'd have to allocate the memory for the object using malloc() and use placement new. Maybe some class/struct specific overload of operator new could be used...

1 Comment

I was able to use a designated initializer to set the size: { .buf[SIZE-1] = 0 }. Does Not work with all compilers though :(
2
class Foo {
    int a[]; // OK in C, invalid in C++. Does not work with inheritance.
}; // Idea is that structure is "extended" indefinitely by an array.
   // May work on your compiler as an extra feature.

int a[];     // error in C and C++: storage size of 'a' isn't known

void bar() {
    int a[]; // error in C and C++: storage size of 'a' isn't known
}

extern int a[]; // OK: storage size may be declared later.

int a[5]; // declaration of size before use.

An array type with unspecified size is incomplete. 8.3.4/1:

If the constant expression is omitted, the type of the identifier of D is “derived-declarator-type-list array of unknown bound of T”, an incomplete object type.

It must be completed in order to participate in a definition, ie the definition of a must contain a size specification or initialization with an array of specified size.

4 Comments

I don't understand the "must be completed before use" comment. It is perfectly legal to use an array of unspecified size in C++. You can't apply sizeof to it, but you can legally access its elements.
@Andrey: A function argument declared as an array of unspecified size has type T*. It is a decay to another type. Is there another example I should be aware of? Your answer doesn't seem to show any.
I wasn't talking about function arguments, which is a completely different story. I was referrring to the extern int a[] declaration in your example. Once you declare an array like that, you can use it already. I see you removed the reference to "use".
@Andrey: I meant "use" the type to define something, sorry.
-1

We've used this to denote a variable length record of some sort. Something like a header file that has information on how many structures to follow, followed by the data itself. It's a variable length array and I've found it is not supported well between compilers. Some want array[]; and some want array[0]; (old style).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.