The struct hack where you have an array of length 0 as the last member of a struct from C90 and C99 is well known, and with the introduction of flexible array members in C99, we even got a standardized way of using it with []
. Unfortunately, C++ provides no such construct, and (at least with Clang 3.4), compiling a struct with either [0]
or []
will yield a compilation warning with --std=c++11 -pedantic
:
$ cat test.cpp
struct hack {
char filler;
int things[0];
};
$ clang++ --std=c++11 -pedantic test.cpp
\test.cpp:3:14: warning: zero size arrays are an extension [-Wzero-length-array]
int things[0];
and similarly
$ cat test.cpp
struct fam {
char filler;
int things[];
};
$ clang++ --std=c++11 -pedantic test.cpp
\test.cpp:3:7: warning: flexible array members are a C99 feature [-Wc99-extensions]
int things[];
My question then is this; say that I want to have a struct that contains an array of variable size as the last item in C++. What is the right thing to do given a compiler that supports both? Should I go with the struct hack [0]
(which is a compiler extension), or the FAM []
(which is a C99 feature)? As far as I understand it, either will work, but I am trying to figure out which is the lesser evil?
Also, before people start suggesting keeping an int*
to a separately allocated piece of memory in the struct instead, that is not a satisfactory answer. I want to allocate a single piece of memory to hold both my struct and the array elements. Using a std::vector also falls into the same category. If you wonder why I don't want to use a pointer instead, the R.'s answer to another question gives a good overview.
There have been some similar questions elsewhere, but none give an answer to this particular question:
- Are flexible array members valid in C++?: Very similar, but the question there is whether FAM is valid in C++ (no). I am looking for a good reason to pick one or the other.
- Conforming variant of the old “struct hack”: Proposes an alternative, but it's neither pretty, nor always correct (what if padding is added to the struct?). Accessing the elements later is also not as clean as doing
e.things[42]
.
int things[1];
? For implementations where the struct hack is no issue, there's no inherent problem if there's padding, and accessing the elements later on is perfectly fine. You only have a tad more work when allocating it if you do not want to waste the space of 1 element + the possible padding. – Carmenfiller
member? Does this struct only contain a dynamic array? – Dosagefiller
argument is just there to avoid the compiler complaining about a zero-size struct in the simplified example struct. It could have been an arbitrary number of other fields of various types, but that would have unnecessarily complicated the question. – Bimonthly