Are flexible array members valid in C++?
C++ was first standardized in 1998, so it predates the addition of flexible array members to C (which was new in C99). There was a corrigendum to C++ in 2003, but that didn't add any relevant new features. The next revision of C++ (C++2b) is still under development, and it seems flexible array members still aren't added to it.
C++ doesn't support C99 flexible array members at the end of structures, either using an empty index notation or a 0
index notation (barring vendor-specific extensions):
struct blah
{
int count;
int foo[]; // not valid C++
};
struct blah
{
int count;
int foo[0]; // also not valid C++
};
As far as I know, C++0x will not add this, either.
However, if you size the array to 1 element:
struct blah
{
int count;
int foo[1];
};
the code will compile, and work quite well, but it is technically undefined behavior. You can allocate the appropriate memory with an expression that is unlikely to have off-by-one errors:
struct blah* p = (struct blah*) malloc( offsetof(struct blah, foo[desired_number_of_elements]);
if (p) {
p->count = desired_number_of_elements;
// initialize your p->foo[] array however appropriate - it has `count`
// elements (indexable from 0 to count-1)
}
So it's portable between C90, C99 and C++ and works just as well as C99's flexible array members.
Raymond Chen did a nice writeup about this: Why do some structures end with an array of size 1?
Note: In Raymond Chen's article, there's a typo/bug in an example initializing the 'flexible' array. It should read:
for (DWORD Index = 0; Index < NumberOfGroups; Index++) { // note: used '<' , not '='
TokenGroups->Groups[Index] = ...;
}
The second one will not contain elements but rather will point right after blah
. So if you have a structure like this:
struct something
{
int a, b;
int c[0];
};
you can do things like this:
struct something *val = (struct something *)malloc(sizeof(struct something) + 5 * sizeof(int));
val->a = 1;
val->b = 2;
val->c[0] = 3;
In this case c
will behave as an array with 5 int
s but the data in the array will be after the something
structure.
The product I'm working on uses this as a sized string:
struct String
{
unsigned int allocated;
unsigned int size;
char data[0];
};
Because of the supported architectures this will consume 8 bytes plus allocated
.
Of course all this is C but g++ for example accepts it without a hitch.