[C con Clase] Punteros arrays y memoria.

Steven Davidson steven en conclase.net
Vie Ene 12 16:29:21 CET 2007


Hola Sorcerer,

El pasado 2007-01-11 22:22:56, Sorcerer escribió:
 
S> Estaba probando ese código y encontré un problema, creo que también encontré
S> la explicación pero quisiera confirmar...

Veamos las conclusiones y comentarios que has hecho.

S> Resulta que intenté ver los tamaños de las matrices con sizeof, hice lo
S> siguiente:

Esto depende de cuál versión del código estás analizando. Supongo que te refieres al código con punteros y memoria dinámica.

S> -   printf("Peso de la matriz: %i\n", sizeof(*A)*2);
S> Multiplico por 2 xq supuse que como no era un array con [], entonces por eso
S> sizeof solo me daba el tamaño del primer elemento (en este caso, del primer
S> puntero).

Ciertamente, 'sizeof(*A)' te dará el tamaño en bytes del valor apuntado. Como 'A' es un doble puntero, '*A' es un puntero (singular). Lo más seguro es que te dará 4 bytes.

Sin embargo, no podemos calcular la cantidad de bytes de lo que ocupa todos los elementos de esta manera. Recuerda que 'new[]' pide memoria al sistema operativo. Si el S.O. puede llevar a cabo la petición, entonces éste devolverá la dirección de memoria del bloque pedido. Viendo que hacemos tres peticiones de memoria (tres 'new[]'), o en general (N+1) * 'new[]', no podemos garantizar que todos los bloques existan contiguamente entre sí. Por esta razón, no podemos usar 'sizeof' con la matriz dinámica para determinar su cantidad total. Sí podemos hacerlo con un array (estático) porque éste sí garantiza la contigüidad de sus elementos.

S> -   printf("Peso del puntero a puntero **A: %i\n", sizeof(A));
S> Con ese mismo principio, este me debía dar el tamaño del primer y único
S> puntero a puntero.

Sí. Como se trata de un puntero, lo más seguro es que sea 4 bytes.

S> -  printf("Peso de los int guardados en la matriz: %i\n", &A[1][3] - *A);
S> Y aquí esta mi problema, eso no funciona. &A[1][3] Me debería devolver la
S> dirección de memoria pasados el último elemento (xq solo llega hasta
S> A[1][2]) y *A me debería devolver la dirección de memoria del primer
S> elemento (del primer puntero). Si estuvieran en posiciones contiguas de
S> memoria, me debería dar 6, ya que tengo 6 punteros almacenados (usé el
S> código de Daniel y si arreglé el problema de las dimensiones de las
S> matrices)... sin embargo me da 9 :S

Nuevamente, no podemos asegurar que los bloque de memoria son contiguos al usar técnicas dinámicas. Esto puede ser que sea así, o no; en general, seguramente no.

S> Mi teoría era que si multiplicaba el resultado de esa resta por 4, obtendría
S> el peso total de todos los int guardados en la matriz.
S> La explicación pienso que es esta: "Esto es porque creamos varios bloque de
S> memoria contigua pero de cantidades más pequeñas. Tomando el ejemplo
S> anterior, tendríamos 10.000 bloques de 39 KB. Esto es más plausibled, ya que
S> puede haber varios fragmentos de memoria libre para poder reservar bloques
S> de 39 KB."
S> Pero no se.... porque también observé esto otro:
S> Ahora, 9*4 = 36, que es el total de memoria que utiliza el array. (9 es el
S> valor que me daba la resta de punteros, y 4 es el peso de un int)

Me temo que esto no es correcto. Simplemente has elegido un número a multiplicar para que salieran bien los cálculos. Te pongo un ejemplo, para que veas que lo anterior no funcionaría:

int **A = new int*[2];  //  A = 1000
A[0] = new int[3];  // A[0] = 5000
A[1] = new int[3];  // A[1] = 700
...
&A[1][3] <= 703
*A       <= 5000

&A[1][3] - *A = 703 - 5000 = -4297

Como puedes ver, esto no tiene ningún sentido. Multiplicando el resultado anterior por 4 tampoco nos ayuda: -17188.

Reitero que no podemos garantizar las direcciones de memoria que nos dé el sistema operativo.

S> Usando esta formula:
S> "cantidad_total = N * M * 4 + N * 4 + 4
S>               = 4 * (N * M + N + 1)"
S> 2*3*4 + 2*4 + 4 = 36
S> Entonces... ¿Es que se guardaron, punteros y enteros, en posiciones
S> contiguas de memoria, y al restar obtengo ese valor?. Pienso que podría ser,
S> ya que un puntero a char también me usa 4 bytes, o sea, no estaría mal al
S> multiplicar 9*4.
S> Si ese fuera el caso... ¿siempre es así?

Bueno, ya lo he explicado anteriormente. Tu resultado ha sido coincidencia nada más. En general, lo anterior no funcionaría.


Espero haber aclarado el tema.

Steven


Más información sobre la lista de distribución Cconclase