Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static arrays defined with unspecified size, empty brackets?

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.

like image 787
Ahmed Abdelkader Avatar asked Apr 26 '10 23:04

Ahmed Abdelkader


3 Answers

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.

like image 104
AnT Avatar answered Oct 29 '22 11:10

AnT


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 = 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...

like image 33
Michael Burr Avatar answered Oct 29 '22 11:10

Michael Burr


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.

like image 2
Potatoswatter Avatar answered Oct 29 '22 11:10

Potatoswatter