Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are flexible array members valid in C++?

In C99, you can declare a flexible array member of a struct as such:

struct blah {     int foo[]; }; 

However, when someone here at work tried to compile some code using clang in C++, that syntax did not work. (It had been working with MSVC.) We had to convert it to:

struct blah {     int foo[0]; }; 

Looking through the C++ standard, I found no reference to flexible member arrays at all; I always thought [0] was an invalid declaration, but apparently for a flexible member array it is valid. Are flexible member arrays actually valid in C++? If so, is the correct declaration [] or [0]?

like image 580
MSN Avatar asked Dec 10 '10 19:12

MSN


People also ask

How to use flexible array member in C?

To use the flex member as a flexible array member, you'd allocate it with malloc as shown above, except that sizeof(*pe1) (or the equivalent sizeof(struct ex1) ) would be replaced with offsetof(struct ex1, flex) or the longer, type-agnostic expression sizeof(*pe1)-sizeof(pe1->flex) .

How do you declare a flexible array in C++?

In C99, you can declare a flexible array member of a struct as such: struct blah { int foo[]; };

Are arrays flexible?

Java arrays are flexible. For example, in Java you can assign one array to another: int[] a1 = {1, 2, 3, 4}; int[] a2 = {1, 2, 3}; a1 = a2; At first, a1 has index range 0–3, and a2 has index range 0–2.

What is flexible C?

Flexible Array members in a structure in C means we can declare array without its dimension within a structure and its size will be flexible in nature. Flexible array member must be the last member of class.


2 Answers

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.

like image 160
Martin v. Löwis Avatar answered Sep 28 '22 01:09

Martin v. Löwis


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] = ...; } 
like image 23
Michael Burr Avatar answered Sep 28 '22 00:09

Michael Burr