length - Arrays multidimensionales en C: ¿son irregulares?
dynamic array c++ (6)
Esto dependería.
Las matrices multidimensionales en C están organizadas de forma secuencial.
Puede crear matrices dentadas si quiere usar punteros.
Una simple pregunta sobre el lenguaje de programación C (ANSI-C):
¿Las matrices multidimensionales en C son dentadas?
Quiero decir, ¿estamos hablando de "matriz de matrices" (una matriz de punteros a otras direcciones en la memoria), o esto es simplemente "matriz unidimensional larga" (que se almacena secuencialmente en la memoria)?
Lo que me molesta es que estoy algo seguro de que:
matrix[i][j]
es equivalente a * ( * (matrix + i) + j)
Si declaras una matriz multidimensional, obtienes una "matriz unidimensional larga" (que se almacena secuencialmente en la memoria).
Si declara un puntero a puntero (a puntero ....) obtiene matrices de matrices.
Esta diferencia es fuente de mucha confusión para los programadores principiantes C.
Tienes razón, esa matrix[i][j]
es equivalente a *(*(matrix + i) + j)
, ya que arr[i]
es equivalente a *(arr + i)
. Sin embargo, tenga en cuenta que si arr
está declarado como
int arr[64];
entonces cualquier referencia a arr
puede convertirse implícitamente en &arr[0]
, que es un puntero al primer elemento. Lo mismo sucede con las matrices de matrices:
int matrix[8][8];
Aquí la matrix
tiene el tipo int[8][8]
, que se convierte automáticamente en int (*)[8]
cuando se le agrega un entero, como en matrix + i
. Entonces *(matrix + i)
tiene tipo int[8]
, que se convierte nuevamente a int *
cuando se agrega j
, entonces *(matrix + i) + j
tiene tipo int *
, por lo tanto *(*(matrix + i) + j)
tiene tipo int
como se esperaba.
Entonces, el punto es que las matrices no son punteros , sino que se pueden convertir implícitamente en un puntero a su primer elemento.
Entonces, si asigna matrices de matrices como las anteriores ( int matrix[8][8];
), entonces todos los elementos son consecutivos en la memoria.
Una matriz multidimensional en C es contigua. El seguimiento:
int m[4][5];
consiste en 4 int[5]
s dispuestos uno al lado del otro en la memoria.
Una variedad de punteros:
int *m[4];
es irregular Cada puntero puede señalar (el primer elemento de) una matriz separada de una longitud diferente.
m[i][j]
es equivalente a *(*(m+i)+j)
. Ver el estándar C11 , sección 6.5.2.1:
La definición del operador de subíndice [] es que E1 [E2] es idéntico a (* ((E1) + (E2)))
Por lo tanto, m[i][j]
es equivalente a (*(m+i))[j]
, que es equivalente a *(*(m+i)+j)
.
Esta equivalencia existe porque en la mayoría de los contextos, las expresiones del tipo de matriz decaen a los punteros a su primer elemento (estándar C11, 6.3.2.1). m[i][j]
se interpreta de la siguiente manera:
-
m
es una matriz de matrices, por lo que se desintegra a un puntero am[0]
, la primera subcadena. -
m+i
es un puntero ali
th subcampo dem
. -
m[i]
es equivalente a*(m+i)
, desreferenciando un puntero ali
subcampo dem
. Como esta es una expresión del tipo de matriz, se desintegra a un puntero am[i][0]
. -
m[i][j]
es equivalente a*(*(m+i)+j)
, desreferenciando un puntero alj
ésimo elemento deli
ésimo subconjunto dem
.
Tenga en cuenta que los punteros a las matrices son diferentes de los punteros a su primer elemento. m+i
es un puntero a una matriz; no es una expresión del tipo de matriz, y no decae, ya sea a un puntero a un puntero oa cualquier otro tipo.
Una matriz o matrices, como la int matrix[A][B]
no es irregular, ya que cada elemento de la matrix
es una array of B int
.
Desea saber que el resultado de *(*(matrix+i)+j)
es y compárelo con el resultado de la matrix[i][j]
.
Dado que el tipo de matrix
es una array of A array of B int
, entonces la expresión matrix+i
es un puntero que apunta a la i
ésima array of B int
de la matrix
, y su tipo es int (*)[B]
. La desreferenciación de esta expresión da como resultado una array of B int
. La expresión *(matrix+i)+j)
da como resultado un puntero al j
th int
de esa matriz. La desreferenciación de esa expresión da como resultado un int
. Esto es equivalente a lo que haría la expresión matrix[i][j]
.
Una matriz de punteros, como int *matrix[A]
, puede ser irregular, ya que cada elemento de la matrix
puede apuntar a una asignación de tamaño diferente.
Un área de memoria consecutiva:
int arr[N][M];
Un área de memoria no consecutiva:
int** arr = malloc(N*sizeof(int*));
for (int i=0; i<N; i++)
arr[i] = malloc(M*sizeof(int));
Puede usar arr
como una matriz bidimensional (por ejemplo, arr[1][2] = 3
) en ambos casos. Pero puede aplicar con seguridad operaciones de copia más grandes, como memset(arr,0,N*M*sizeof(int))
, solo en el primer caso.