
usuario366312
¿Crees qué esta discusión sobre el mapa de memoria de la matriz 2D es correcto? ¿Especialmente esta foto? ¿Puedes explicar la teoría?
Supongamos que declaramos una matriz 2D en C como esta:
int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
Ahora, de acuerdo con esta discusión, la memoria estaría dispuesta de la siguiente manera:

Ahora, he escrito el siguiente código para probar esta teoría:
#include <stdio.h>
main()
{
int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
printf(" arr==%d\n", arr);
printf(" &arr[0]==%d\n", &arr[0]);
printf(" arr[0]==%d\n", arr[0]);
printf("&arr[0][0]=%d\n", &arr[0][0]);
printf(" arr[0][0]=%d\n", arr[0][0]);
}
/*
Output:
========
arr ==1245028
&arr[0] ==1245028
arr[0] ==1245028
&arr[0][0]==1245028
arr[0][0]==10
Press any key to continue...
*/
¿Por qué las primeras 4 salidas son iguales?

Chris Cooper
Mira mi pregunta aquí.
Esa no es la forma en que accede a la información sobre matrices bidimensionales. De hecho, puedes pensar en ellos como 1-d, donde multiplicas y sumas los índices de una manera especial.
p.ej
int x[10] = {0,1,2,3,4,5,6,7,8,9};
int y[2][5] = {{0,1,2,3,4},{5,6,7,8,9}};
Estos tienen el mismo formato en la memoria y se ven así:
|0|1|2|3|4|5|6|7|8|9|
Así que para obtener el 8
elemento, puede solicitar x[8]
o y[1][3]
.
Para la segunda forma, puedes pensar en ella como (1 * 5) + 3
.
Es por eso que sus primeros 4 fueron iguales. Tu tienes:
arr
: esta es la dirección del inicio de la matriz
arr[0]
: esta es la dirección del inicio del primer subarreglo, que es el mismo que el inicio del arreglo general
&arr[0][0]
: esta es la dirección del primer elemento del primer subconjunto, también el inicio del conjunto general
arr[0][0]
: este es el valor almacenado en el primer elemento del primer subarreglo.
Tu código solo usa una matriz multidimensional simple, pero la imagen describe una matriz de punteros, como el tipo que normalmente haces al ubicar cosas.
Una matriz multidimensional es básicamente una matriz normal, aplanada (en la memoria) con algo de azúcar sintáctico adicional para acceder. Entonces, si bien es posible obtener un puntero de arr[i]no hay una “variable” adicional solo para almacenar esto, como sucede en su imagen.
Para corregir la imagen, retire las partes con el arr[0], arr[1]...
y cambiar el valor de arr
para 1245039
(lo mismo que &arr[0][0]).
Las primeras cuatro salidas son las mismas para obtener la dirección del primer elemento de la matriz, es decir, &arr[0][0]. La última salida es su contenido.

shelleymariposa
bueno, por lo que recuerdo, en C ++ (y creo que C, aunque ese no es mi fuerte) una matriz 2d declarada como Values[][]
generalmente (no sé si siempre) se implementa como una matriz de matrices de estilo C. sin embargo, cuando los declara en la pila (por ejemplo, una variable local), creo que el formato de la memoria es diferente.
entonces, cuando declaras una variable local, todo está dispuesto como si era solo una matriz 1d, y obtienes las cosas dispuestas de tal manera que realmente puedes convertir a un puntero y luego acceder como una matriz 1D. (!) Sin embargo, todavía se reconoce de la misma manera que una matriz 2D normal dentro del alcance de la declaración, y posiblemente si pasa a un parámetro que se declara con el []
notación.
pero, si asigna uno de estos en el montón (por ejemplo, global o estático o vía nuevo), la historia es diferente. ahora, la memoria se presenta como una matriz real de matrices, por lo que los resultados reales de las ubicaciones de memoria que indexa si convierte a una matriz 1D y el índice ahora serán punteros.
verifiqué mi recuerdo haciendo lo siguiente: creé int HeapArray[3][3];
como mundial y int StackArray[3][3];
como local (ambos con inicializadores de { { 10, 20, 30 }, {40, 50, 60}, {70, 80, 90 } }
). dentro de mi función, los arrojo a ambos a un puntero int, int* ptrHeapArray = (int*)HeapArray;
y int* ptrStackArray = (int*)StackArray;
y luego miré el valor de retorno del elemento 0 de cada uno.
[edit: whoops, i had them reversed; fixed now]
ptrStackArray[0]
era igual a 10
ptrHeapArray[0]
era igual a un puntero a int[3];
así que creo que mi recuerdo limitado es exacto. 🙂 ¡espero que esto ayude!
Creo que la verdadera pregunta es si hay una diferencia entre
int **arr
yint arr[][]
– ninguna de las respuestas aborda eso.– Sorén
13 de julio de 2011 a las 9:27