Inicialización de matriz multidimensional en C

Estoy leyendo el libro “Programming in C” de Kochen y estoy confundido cuando explica la inicialización de la matriz multidimensional.

aquí

En particular, no entiendo el significado de la siguiente oración. Tenga en cuenta que, en este caso, se requieren los pares internos de llaves para forzar la inicialización correcta. Sin ellos, las dos primeras filas y los dos primeros elementos de la tercera fila se habrían inicializado en su lugar. No estoy seguro de qué diablos significa la frase.

Con los tirantes internos, la matriz se ve así:

10 5 -3 0 0 9 0 0 0 0 32 20 1 0 0 0 0 8 0 0 

Entonces, en cada línea, los últimos 2 valores son cero (porque no se estableció un valor para ellos. Sin las llaves internas, la matriz se vería así:

 10 5 -3 9 0 0 32 20 1 0 0 8 0 0 0 0 0 0 0 0 

Solo los primeros 12 elementos se convertirán en los valores dados y el rest será 0.

Esto se debe a que la matriz M[4][5] tiene 20 elementos (4 filas, 5 columnas), y el orden predeterminado para la inicialización es fila por fila si las filas no se especifican explícitamente mediante el uso de pares internos de llaves.

Lo que esto significa es que si asigna los mismos 12 valores como una lista lineal simple, sin los pares internos de llaves, entonces los valores se asignan a las primeras dos filas (2 * 5 = 10 elementos) más las 2 primeras columnas de la tercera fila. (Los 8 elementos restantes de la matriz que no inicializó explícitamente se establecerán automáticamente en 0).

El comstackdor de C es consciente de que cada fila solo tiene 5 columnas, y ajustará automáticamente la lista de números en la siguiente fila cada vez que se scope el margen de 5 columnas. Así,

 int M[4][5] = {10, 5, -3, 9, 0, 0, 32, 20, 1, 0, 0, 8}; 

se entiende que significa

 int M[4][5] = { {10, 5, -3, 9, 0}, { 0, 32, 20, 1, 0}, { 0, 8, 0, 0, 0}, { 0, 0, 0, 0, 0} }; 

Puede anular el orden predeterminado utilizando llaves internas para separar sus 12 valores en filas de su propio gusto (pero, naturalmente, no más de 5 columnas por fila para esta definición de una matriz M ).

Por ejemplo, cuando usa llaves internas para separar los mismos 12 valores en cuatro conjuntos de 3 como muestra su página del libro , entonces esas llaves internas se interpretan para inicializar filas separadas de la matriz multidimensional. Y el resultado será inicializar cuatro filas de la matriz, pero solo las primeras 3 columnas de esas cuatro filas, estableciendo las columnas restantes en cero (dos valores de cero en blanco al final de cada fila).

Es decir, el comstackdor de C es consciente de que la matriz M tiene 5 columnas en cada fila, por lo que agregará las columnas faltantes a cada fila, de modo que cada fila tenga 5 columnas, y la matriz tendrá un total de 20 valores:

 int M[4][5] = { {10, 5, -3}, { 9, 0, 0}, {32, 20, 1}, { 0, 0, 8} }; 

se entiende que significa

 int M[4][5] = { {10, 5, -3, 0, 0}, { 9, 0, 0, 0, 0}, {32, 20, 1, 0, 0}, { 0, 0, 8, 0, 0} }; 

Dado que todas las matrices se comportan internamente como matrices 1d, debe especificar con los corchetes las filas que inicializa exactamente.

Por ejemplo:

 int a[4][5] = { { 1, 2, 3 }, // those are the elements of the first row. // only the first 3 elements are initialized { 1, 2, 3, 4} // those are the elements of the 2nd row. // only the first 4 element are initialized }; // everything else will be equal to 0 

mientras

 int a[4][5] = { 1, 2, 3, 1, 2, 3, 4}; // this will initialize first 5 elements // of the first row and then continue // with the 2nd one making the first 2 // elements to be 3 and 4 respectivly // everything else will be equal to 0 

Ayudaría a ver el ejemplo específico.

Una matriz multidimensional es una matriz de matrices. (No es solo azúcar sintáctica para una larga matriz unidimensional).

En un inicializador, es legal omitir tanto los elementos finales (que se inicializan implícitamente a cero) como las llaves internas.

Dado:

 int arr[2][2]; 

una inicialización completa podría verse como:

 int arr[2][2] = { { 10, 20 }, { 30, 40 } }; 

Puede (pero IMHO no debería) omitir las llaves internas:

 int arr[2][2] = { 10, 20, 30, 40 }; 

y el comstackdor asignará los elementos del inicializador a los elementos de arr .

Si omites los elementos finales:

 int arr[2][2] = { { 10, 20 } }; 

luego la segunda fila se inicializa implícitamente a { 0, 0 } .

O podrías escribir:

 int arr[2][2] = { { 10 }, { 20 } }; 

que asignaría los valores 10 y 20 al primer elemento de cada fila, no a la primera fila.

Nuevamente, es difícil decir exactamente de qué hablaba el autor sin ver un ejemplo, pero un refuerzo interno le dice al comstackdor que comience una nueva fila, incluso si la primera fila está incompleta.

Si suministra inicializadores para los 4 elementos (o más generalmente, todos los elementos X * Y ), las llaves internas no son estrictamente necesarias; El orden de los elementos es el mismo de cualquier manera.

Personalmente, me parece mucho más claro incluir todas las llaves internas de todos modos, porque reflejan la estructura real que estás inicializando.

(Entonces, ¿cuál es la diferencia entre una matriz unidimensional y una matriz bidimensional, aparte del azúcar sintáctico? Dada la statement anterior de arr , si fuera lo mismo que una matriz unidimensional, arr[0][2] sería sea ​​igual que arr[1][0] , con el segundo índice desbordado en la segunda fila. Y puede funcionar de esa manera en la práctica, pero en realidad arr[0][2] tiene un comportamiento indefinido. Esto tiene consecuencias prácticas; un comstackdor optimizador puede asumir que todos los límites están dentro del rango, y generar código que se comporte mal si se viola esa suposición).

Véase también esta pregunta .

Las matrices multidimensionales en C son simplemente “azúcar sintáctica” para matrices unidimensionales. Cuando asigna una matriz int 4 x 5, realmente está asignando espacio para 20 enteros en una fila en la memoria. Estos enteros se almacenan como todos los elementos de la primera fila, luego todos los elementos de la segunda fila, etc.

Sin las llaves internas, su inicializador también es 1D, e indica que desea inicializar los primeros 12 de estos 20 enteros, es decir, las primeras dos filas y los dos primeros elementos de la tercera fila.