Tengo una pregunta con respecto a las matrices bidimensionales en C. Ahora sé (por la experiencia directa del compilador) que no puedo inicializar dicha matriz de manera análoga a las matrices unidimensionales como esta:
int multi_array[][] = {
{1,2,3,4,5},
{10,20,30,40,50},
{100,200,300,400,500}
};
> compiler output:
gcc -o arrays arrays.c
arrays.c: In function ‘main’:
arrays.c:8:9: error: array type has incomplete element type
La solución más cercana que funciona es proporcionar el número de columnas explícitamente así:
int multi_array[][5] = {
{1,2,3,4,5},
{10,20,30,40,50},
{100,200,300,400,500}
};
Mi pregunta es: ¿se puede hacer bien? sin proporcionando el número explícitamente (que, después de todo, el compilador debería poder inferir por sí mismo)? No estoy hablando de construirlo manualmente con malloc
o algo así, sino más bien algo cercano a lo que probé. Además, ¿puede alguien que conozca los compiladores de C explicar desde una perspectiva de bajo nivel por qué mi intento inicial no funciona?
usé simple gcc
sin opciones no estándar para compilar el código.
Gracias
Puede hacer esto usando la función de literal compuesto C99.
Una idea parcial es que la longitud de una lista de inicializadores se puede determinar así:
sizeof (int[]){ 1, 2, 3, 4, 5 } / sizeof(int)
Necesitamos una solución para el hecho de que la única forma en que puede pasar un argumento que contiene una coma a una macro es poner paréntesis alrededor (parte de) el argumento:
#define ROW(...) { __VA_ARGS__ }
Luego, la siguiente macro deduce la segunda dimensión de la primera fila:
#define MAGIC_2DARRAY(type, ident, row1, ...) \
type ident[][sizeof (type[])row1 / sizeof (type)] = { \
row1, __VA_ARGS__ \
}
Solo funciona si hay al menos dos filas.
Ejemplo:
MAGIC_2DARRAY(int, arr, ROW(7, 8, 9), ROW(4, 5, 6));
Probablemente no quiera usar esto en un programa real, pero es posible.
Para pasar este tipo de matriz a funciones, la función de matriz de longitud variable C99 es útil, con una función como:
void printarr(int rows, int columns, int array[rows][columns]) { ... }
llamado:
printarr(sizeof arr / sizeof arr[0], sizeof arr[0] / sizeof arr[0][0], arr);
matrices 2D en C
se almacenan en ubicaciones de memoria contiguas. Entonces, si no proporciona el número de filas o el número de columnas, ¿cómo sabrá el compilador cuántas filas y columnas hay?
Para fila matriz principal, el contenido de las filas está en posiciones de memoria contiguas. Por lo tanto, debe especificar al menos el número de columnas. De manera similar, para una matriz principal de columnas, debe especificar al menos el número de filas. La arquitectura define si es fila principal o columna principal. Parece que lo que tiene es una gran arquitectura fila.
-
Sí, pero en el caso del autor de la pregunta, está proporcionando los inicializadores, y a partir de eso, el compilador podría inferir el tamaño de la primera dimensión que el autor de la pregunta ha comentado en su pregunta.
– Jabberwocky
28 de febrero de 2014 a las 16:29
No es una respuesta directa a esas preguntas en la publicación original, solo quiero señalar que lo que propone el autor de la pregunta puede no ser una idea tan buena o útil.
De hecho, el compilador puede inferir de
int multi_array[][] = {
{1,2,3,4,5},
{10,20,30,40,50},
{100,200,300,400,500}
};
la estructura de multi_array
.
Pero cuando desea declarar y definir una función (esta declaración y definición podría estar en otra unidad de compilación o archivo fuente) eso supone aceptar multi_array
como uno de sus argumentos, aún necesita hacer algo como
int foo(..., int multi_array[][COL], ...) { }
El compilador necesita esto COL
hacer aritmética de punteros adecuada en foo()
.
Por lo general, definimos COL
como una macro que será reemplazada por un número entero en un archivo de encabezado, y utilícelo en las definiciones de multi_array
y foo()
:
int multi_array[][COL] = { ... };
int foo(..., int multi_array[][COL], ...) { }
Al hacer esto, es fácil asegurarse de que sean iguales. Y deja que el compilador infiera la estructura de multi_array
de acuerdo con su inicialización, cuando le da una inicialización incorrecta, en realidad introduce un error en su código.
No, no puedes hacerlo. Si ni siquiera inicializa, no puede definir una matriz int[][];
Cree una estructura con matrices 1d. Sin embargo, si sigue este método, puede crear nuevas matrices, pero será una llamada de función para cambiar tamaños y valores. Un enfoque de matriz dinámica podría estar cerca de resolver su problema.
-
Será mejor abordar el problema de OP. Dijo en la pregunta que no quiere oír hablar de la asignación dinámica.
– Um Nyobe
28 de febrero de 2014 a las 16:47
-
Será mejor abordar el problema de OP. Dijo en la pregunta que no quiere oír hablar de la asignación dinámica.
– Um Nyobe
28 de febrero de 2014 a las 16:47
¿Cómo vas a declarar una función que usa
multi_array
como uno de sus parámetros?– Lee Duhem
28 de febrero de 2014 a las 16:27
en el primer caso, el compilador puede inferir tanto la dimensión de
multi_array
pero en este caso, si el programador proporciona diferentes tamaños, dará un error como “tamaño de matriz no coincidente en la inicialización”… Supongo que el diseñador prefirió que el programador indique qué tamaño espera y luego verifique ese tamaño.– Um Nyobe
28/02/2014 a las 16:35
“Además, ¿alguien que conozca los compiladores de C puede explicar desde una perspectiva de bajo nivel por qué mi intento inicial no funciona?” – Porque la especificación requiere tamaños explícitos para todas las dimensiones después de uno. Ahora, por qué ese es el caso, no puedo decir que lo sé.
– Ed S.
28 de febrero de 2014 a las 18:18
@clcto: se puede inferir por la inicialización. Esa es la parte que es confusa, no el hecho de que las dimensiones deban definirse en general.
– Ed S.
28 de febrero de 2014 a las 23:24
Cuando se diseñó C, las computadoras con 16 KB de RAM eran comunes; C se construyó al menos en gran parte sobre una con 8 KB, por lo que es fácil ver por qué no estaba en el lenguaje al principio. ¿Por qué no está en el idioma ahora? A nadie le importó lo suficiente como para cambiar el idioma cuando el editor de cualquier programador puede contar las comas por usted, supongo.
– jthill
26 mayo 2014 a las 17:26