Why does static initialization of flexible array member work?
Asked Answered
S

1

25

I have written the following basic code for a menu:

typedef struct Menu {
    char* title;
    unsigned num_submenus;
    struct Menu *submenu[];
} Menu;

Menu sub1 = {"Submenu 1", 0, {NULL}};
Menu sub2 = {"Submenu 2", 0, {NULL}};
Menu Main = {"Main Menu", 2, {&sub1, &sub2}};   /* No Error?! */

int main()
{
    printf("%s\n", Main.title);
    printf("%s\n", Main.submenu[0]->title);
    printf("%s\n", Main.submenu[1]->title);
}

Browsing through a few related questions it seems like the only way to use a flexible array member is to dynamically allocate memory to it. However my compiler is perfectly happy to compile and run the code without any errors or warnings. Is this verboten?

I am using MinGW gcc 4.6.1 and compiling under C99 rules.

Sachi answered 9/1, 2015 at 0:33 Comment(3)
What error are you expecting?Gunshy
Did you compile using -pedantic that will give an error.Constipation
clang++ 11.0.0 gives: error: initialization of flexible array member is not allowed.Reproduction
R
24

Initialization of flexible array member in this way is not allowed as per C standard.

C11: 6.7.2.1 Structure and union specifiers (p20-21):

21 EXAMPLE 2 After the declaration:

struct s { int n; double d[]; };

the structure struct s has a flexible array member d. [...]

22 Following the above declaration:

struct s t1 = { 0 }; // valid
struct s t2 = { 1, { 4.2 }}; // invalid
t1.n = 4; // valid
t1.d[0] = 4.2; // might be undefined behavior

The initialization of t2 is invalid (and violates a constraint) because struct s is treated as if it did not contain member d. [...]

But, GCC allows the static initialization of flexible array:

GCC Manual: 6.17 Arrays of Length Zero:

Instead GCC allows static initialization of flexible array members. This is equivalent to defining a new structure containing the original structure followed by an array of sufficient size to contain the data. E.g. in the following, f1 is constructed as if it were declared like f2.

 struct f1 {
   int x; 
   int y[];
 } f1 = { 1, { 2, 3, 4 } };

 struct f2 {
   struct f1 f1; 
   int data[3];
 } f2 = { { 1 }, { 2, 3, 4 } };
Radmilla answered 9/1, 2015 at 0:38 Comment(3)
Ah yes, "static" was the word I was missing. Anyway, will this code be allowed in other compilers besides GCC?Sachi
@thndrwrks; See the update. Standard does not allow the static initialization of flexible array.Radmilla
@nyholku; n1570: §6.7.2.1/18*[...]In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.[...]*Radmilla

© 2022 - 2024 — McMap. All rights reserved.