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.
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.
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...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With