Mapa de memoria para una matriz 2D en C

4 minutos de lectura

avatar de usuario
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:

ingrese la descripción de la imagen aquí

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?

  • Creo que la verdadera pregunta es si hay una diferencia entre int **arr y int arr[][] – ninguna de las respuestas aborda eso.

    – Sorén

    13 de julio de 2011 a las 9:27

avatar de usuario
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.

  • Tus matemáticas están un poco mal. Para obtener el 8 elemento que pedirías x[8]no x[9]. Además, el cálculo de un elemento utilizando y[1][3] es (1*5) + 3.

    – Hitesh

    23 mayo 2013 a las 20:28

  • Gracias @Hitesh, lo arreglé. Irónicamente, estaba pensando en términos relativos a un “comienzo de matriz” imaginario para mi ejemplo.

    – Chris Cooper

    30 de mayo de 2013 a las 23:19

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.

avatar de usuario
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!

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad