¿Por qué funciona la inicialización estática del miembro de matriz flexible?

He escrito el siguiente código básico para un menú:

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); } 

Al examinar algunas preguntas relacionadas, parece que la única forma de utilizar un miembro de matriz flexible es asignarle memoria dinámicamente. Sin embargo, mi comstackdor está perfectamente feliz de comstackr y ejecutar el código sin ningún error o advertencia. ¿Esto es verboten?

Estoy usando MinGW gcc 4.6.1 y comstackndo bajo las reglas C99.

De esta manera, no se permite la inicialización del miembro de la matriz flexible según el estándar C.

C11: 6.7.2.1 Especificadores de estructura y unión (p20-21):

21 EJEMPLO 2 Después de la statement:

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

la estructura estructura tiene un miembro de matriz flexible d . […]

22 Siguiendo la statement anterior:

 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 

La inicialización de t2 no es válida (y viola una restricción) porque las struct s se tratan como si no contuvieran el miembro d . […]

Pero, GCC permite la inicialización estática de matriz flexible:

Manual GCC: 6.17 Matrices de Longitud Cero :

En cambio, GCC permite la inicialización estática de miembros de matriz flexible . Esto equivale a definir una nueva estructura que contiene la estructura original seguida de una matriz de tamaño suficiente para contener los datos. Por ejemplo, a continuación, f1 se construye como si se declarara como 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 } };