¿Por qué esto es válido C

Me encontré con este código en reddit . Pensé que las conversiones de tipo habrían causado que esto no fuera válido.

int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 }; 

Al sonar, recibo algunas advertencias sobre elementos y llaves excesivos en un inicializador escalar. Pero el contenido de a es [1, 7, 9] .

¿Es esto realmente legítimo, y si lo es, podría alguien explicar qué está sucediendo exactamente?

Los elementos en exceso son simplemente ignorados. Hay dos partes de 6.7.8 Inicialización que te interesan. Primero, del párrafo 17:

Cada lista de inicialización incluida en corchetes tiene un objeto actual asociado. Cuando no hay designaciones presentes, los subobjetos del objeto actual se inicializan en orden de acuerdo con el tipo del objeto actual: elementos de la matriz en orden creciente de subíndices, miembros de estructura en orden de statement y el primer miembro nombrado de una unión.

Ese explica por qué obtienes 1, 7 y 9: el objeto actual se establece con esas llaves. Luego, en cuanto a por qué no le importan los extras, del párrafo 20:

… solo se toman suficientes inicializadores de la lista para tener en cuenta los elementos o miembros del subagregado o el primer miembro de la unión contenida; cualquier inicializador restante se deja para inicializar el siguiente elemento o miembro del agregado del que forma parte el subagregado actual o la unión contenida.

  int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 }; 

no es válido.

No es válido por las mismas razones int b[1] = {1, 2}; no es válido: porque C99 dice

(C99, 6.7.8p1) “Ningún inicializador intentará proporcionar un valor para un objeto que no esté contenido dentro de la entidad que se está inicializando”.

El último elemento 10 en los inicializadores intenta proporcionar un valor para un objeto que no está contenido dentro de la entidad que se está inicializando.