Punteros, matrices multidimensionales y direcciones

Digamos que tenemos: int A [5] [2] [3]; Ahora, si hago: A [1] [0] [0] = 4; eso significa :

1.) ¿A [1] y A [1] [0] son ​​punteros?

2.) Si A [1] es un puntero, entonces almacenará la dirección del puntero A [1] [0]?

3.) Si A [1] [0] es un puntero, entonces almacenará la dirección de A [1] [0] [0] que NO es un puntero sino solo una variable que almacena el valor de 4?

Si los puntos anteriores son correctos, entonces, ¿por qué dos, el siguiente código nos da la misma dirección de entero:

int main(void) { int A [5] [2] [3]; A[1][0][0]=4; printf("%d\n\n", A[1]); printf("%d\n\n", A[1][0]); printf("%d\n\n",&A[1][0][0]); system("pause"); } 

Aquí, asumo que A [1] es un puntero que apunta a otro puntero A [1] [0] y, por lo tanto, almacena la dirección del puntero A [1] [0]. Y, A [1] [0] es un puntero que apunta a la VARIABLE A [1] [0] [0] y, por lo tanto, almacena la dirección de la VARIABLE A [1] [0] [0].

¡Por favor, ayúdame!

Para responder correctamente a su pregunta, lea en orden de fila mayor, que es cómo se almacenan los arreglos multidimensionales en C. El artículo de Wikipedia es un poco demasiado conciso, pero uno de estos podría ser más claro:

http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html http://archive.gamedev.net/archive/reference/articles/article1697.html http://www.ibiblio.org/ pub / languages ​​/ fortran / append-c.html

También está esta pregunta SO .


Respondiendo directamente a sus puntos, asumiendo que sabe cómo funciona el almacenamiento por filas:

int A[5][2][3] declara una región contigua de memoria que tiene 5 * 2 * 3 pulgadas de longitud: cinco matrices de dos matrices de tres pulgadas cada una. Las matrices se almacenan una al lado de la otra en la memoria lineal, de modo que

 &A[0][0][0] == A &A[0][0][1] == A+1 &A[0][1][0] == A+(1*3) &A[3][1][2] == A+(3*(2*3))+(1*3)+2 

A[1] técnicamente no es un puntero sino una matriz. Es una matriz int [2][3] . Pero me parece mucho menos claro que pensar que considerar que A[5][2][3] es una región plana de memoria, de treinta pulgadas de longitud.

 A[0][0][0] is the first integer in that region. A[0][0][1] is the second integer. A[0][0][2] is the third integer. A[0][1][0] is the fourth integer in this flat region. A[0][1][1] is the fifth integer. And so on until A[1][0][0] is the eleventh integer. 

Por lo tanto, la dirección de A[1][0][0] es diez enteros más allá de A[0][0][0] ; es decir , &A[1][0][0] - &A[0][0][0] == 10 . Debido a que el lenguaje C es muy flexible respecto a la diferencia entre matrices y punteros, A[1] se interpreta como si fuera una dirección cuando se usa en una expresión, aunque realmente signifique “el primer elemento en una matriz de cinco matrices. de dos matrices de tres enteros “que a su vez es” una matriz de dos matrices de tres enteros “.

El resultado es que A[1] no almacena un puntero, es un puntero. Cada dirección de memoria desde &A[0][0][0] a &A[5][2][3]-1 almacena un número entero en su matriz multidimensional.

Lo que estás pensando en los puntos (2) y (3) son matrices de punteros a matrices , que son algo diferente.

Esto es mucho más fácil de explicar con imágenes, por lo que debe encontrar un libro de texto o un artículo adecuado en arrays.

En general, cuando aprenda sobre punteros y matrices en C, le recomiendo que se olvide temporalmente del lenguaje y pretenda que es Dennis Ritchie inventando C en una computadora PDP-11 con 56kb de RAM plana. Obtenga una hoja grande de papel cuadriculado, numere sus celdas consecutivamente, simule que representa su RAM y cada celda es de un byte, y puede trabajar con su puntero matemático con lápiz y papel .

C se inventó en ese entorno y entender sus orígenes hará que el lenguaje moderno sea mucho más sensible.

Como nota al margen, cuando intenté escribir esta respuesta, el lenguaje de marcado de Overflow de Stack cambió repetidamente y arruinó los índices en los ejemplos de mis matrices anteriores. Entonces, si ves números que parecen estar fuera del scope de sus arreglos, es un error introducido por el editor.

Sus suposiciones serían verdaderas si tuviera arreglos dynamics (es decir, asignados con malloc / calloc ).

Las matrices estáticas, sin embargo, se asignan como parte contigua de la memoria y son simplemente punteros al primer elemento. Cuando escribes A[X][Y][Z] es básicamente equivalente a *(A + X*YSIZE*ZSIZE + Y*SIZE + Z) , no a *(*(*(A+X) + Y) + Z) . Esto permite un acceso algo más rápido a los datos (no es necesario acceder a los punteros intermedios), pero requiere que todos los datos se asignen en una sola porción y sean de tamaños regulares.

Aquí hay más información sobre la no intercambiabilidad de matrices estáticas frente a dinámicas en C.

La variable A es 5 * 2 * 3 ints, asignadas juntas como un bloque. (Es decir, 30 pulgadas).

No hay punteros involucrados en la statement `int A [5] [2] [3]; ‘ – el único espacio reservado es mantener los valores de 30 int.

Cuando escribe una expresión usando A y subíndices, porque ha dicho que hay 3 dimensiones, debe proporcionar las 3 para especificar a qué valor int está accediendo o modificando. Si usa menos de 3 subíndices, solo está especificando parcialmente a qué está accediendo; la convención es que dicha referencia se toma como una solicitud de la dirección de la parte relevante del espacio general.

Las matrices multidimensionales en c no hacen uso de punteros. Aunque un acceso de puntero a puntero a puntero puede parecer similar, es posible que los datos reales no sean contiguos, y existe una sobrecarga para almacenar todas las direcciones. El acceso a matrices multidimensionales en C es una forma de azúcar sintáctica:

 char a[5][7][9] a[d][h][w] <<==>> ((char*)a)[((9*7*d)+(9*h)+w] 

Todos los arrays C comparten la propiedad en la que se desintegran (o se convierten automáticamente en punteros al primer elemento del array). Como resultado,

 a[1] (char[7][9]) --decay--> ((*char)[5][9]) pointer to char array &a[1] ((*char)[5][9]) no decay 

Los dos son equivalentes, porque en el último momento “decae” explícitamente el puntero, mientras que sucede automáticamente en el primero.

Leer en fila orden importante

Sí, eso no ayudó en absoluto, estaba pensando que C era la columna principal por un segundo, creo. (olvidando lo que significaba todo eso)

Puede que sea un poco raro, pero aquí está mi explicación. Imagina que tienes seis personas distintas numeradas del 1 al 6, y están alineadas en consecuencia del 1 al 6. Si dijiste que este equipo (las seis personas) está dividido en dos grupos, donde están los primeros tres (1-3) en el grupo A, y el rest (4-6) están en el grupo B.

[1 2 3] [4 5 6]

Entonces, si te digo quién es el primero en el EQUIPO? ¡Dirías el primero! ¿Pero si te pregunto quién es el primer miembro del GRUPO A de EL EQUIPO? Es lo mismo, la primera persona!

Además, si te digo quién es el cuarto miembro del equipo? ¡Dirías el cuarto! Entonces, ¿qué pasa si te pregunto quién es el primer miembro del GRUPO B de THE TEAM? Es el mismo, el cuarto.


Te sucede la misma historia; A [1] es un puntero al comienzo de la gran matriz (The Team), donde A [1] [0] indica que apunta al comienzo de la primera matriz interna (EL PRIMER GRUPO) dentro de la gran matriz (A [ 1]), que es idéntico! Entonces dices, & A [1] [0] [0], que es como preguntar al primer miembro de la primera matriz interna que reside en la matriz grande, ¿cuál es tu número? Entonces, él volverá a reproducir el mismo.

Lo que difiere es el tipo de punteros y cómo se interpretan, pero sus valores son idénticos . Esto porque los arreglos almacenan elementos de manera contigua.