Asignación de memoria para elementos de estructuras.

Hola, estoy teniendo dificultades para comprender cómo se asigna la memoria a los elementos de la estructura.

Por ejemplo, si tengo la siguiente estructura y el tamaño de char es 1 e int es de 4 bytes respectivamente.

struct temp { char a; int b; }; 

Soy consciente de que el tamaño de la estructura sería 8. Debido a que habrá un relleno de 3 bytes después del carácter, y el siguiente elemento se debe colocar en múltiplos de 4 para que el tamaño sea 8.

Ahora considere la siguiente estructura.

 struct temp { int a; // size is 4 double b; // size is 8 char c; // size is 4 double d; // size is 8 int e; // size is 4 }; 

Este es el o / pi obtenido para la estructura anterior.

 size of node is 40 the address of node is 3392515152 ( =: base) the address of a in node is 3392515152 (base + 0) the address of b in node is 3392515160 (base + 8) the address of c in node is 3392515168 (base + 16) the address of d in node is 3392515176 (base + 24) the address of e in node is 3392515184 (base + 32) 

La memoria total sum hasta 36 bytes, ¿por qué se muestra como 40 bytes? Si creamos una matriz de dicha estructura, también el primer elemento del siguiente elemento de la matriz se puede colocar en 3392515188 (base + 36) ya que es un múltiplo de 4, pero ¿por qué no sucede así?

¿Puede alguien por favor resolver mi duda.

Gracias de antemano, Saravana

Parece que en tu sistema, el double tiene que tener la alineación de 8.

 struct temp { int a; // size is 4 // padding 4 bytes double b; // size is 8 char c; // size is 1 // padding 7 bytes double d; // size is 8 int e; // size is 4 // padding 4 bytes }; // Total 4+4+8+1+7+8+4+4 = 40 bytes 

El comstackdor agrega 4 bytes adicionales al final de la estructura para asegurarse de que la array[1].b esté alineada correctamente.

Sin relleno final (asumiendo que la matriz está en la dirección 0):

 &array[0] == 0 &array[1] == 36 &array[1].b == 36 + 8 == 44 44 % 8 == 4 -> ERROR, not aligned! 

Con el relleno final (asumiendo que la matriz está en la dirección 0):

 &array[0] == 0 &array[1] == 40 &array[1].b == 40 + 8 == 48 48 % 8 == 0 -> OK! 

Tenga en cuenta que los tamaños, alineaciones y rellenos dependen del sistema de destino y del comstackdor en uso.

En su cálculo, ignora el hecho de que e está sujeto a ser rellenado:

La estructura parece

 0 8 16 24 32 AAAAaaaaBBBBBBBBCcccccccDDDDDDDDEEEEeeee 

donde mayúscula es la variable en sí, y minúscula es el relleno que se le aplica.

Como puede ver (y también de las direcciones), cada campo se rellena a 8 bytes, que es el campo más grande de la estructura.

Como la estructura se puede usar en una matriz, y todos los elementos de la matriz también deben estar bien alineados, el relleno para e es necesario.

Depende en gran medida de su architecture de procesador y comstackdor. Las máquinas y comstackdores modernos pueden elegir un relleno más grande o más pequeño para reducir el costo de acceso a los datos.

La alineación de cuatro bytes significa que dos líneas de dirección no se utilizan. Ocho, tres Un chip puede usar eso para abordar más memoria (grano grueso) con la misma cantidad de hardware.

Un comstackdor puede usar un truco similar por varias razones, pero no se requiere que el comstackdor haga nada pero no sea menos detallado que el procesador. A menudo, solo toman el valor de mayor tamaño y lo usan exclusivamente para ese bloque. En tu caso, eso es un double , que es de ocho bytes.

Este es un comportamiento dependiente del comstackdor. Algunos comstackdores hacen que ese “doble” se almacene después de un desplazamiento de 8 bits.

Si modifica la estructura como se muestra a continuación obtendrá un resultado diferente.

 struct temp { double b; // size is 8 int a; // size is 4 int e; // size is 4 double d; // size is 8 char c; // size is 4 } 

Todo progtwigdor debe saber qué tipo de relleno está haciendo el comstackdor. Por ejemplo, si está trabajando en la plataforma ARM y establece la configuración del comstackdor para que no rellene los elementos de la estructura [, entonces el acceso a los elementos de la estructura a través de los punteros puede generar una dirección ‘impar’ para la cual el procesador genera una excepción.

Cada estructura también tendrá requisitos de alineación.

por ejemplo :

typedef struct structc_tag {char c; “ double d; int s; } structc_t;

Aplicando el mismo análisis, structc_t necesita sizeof (char) + 7 bytes de relleno + sizeof (double) + sizeof (int) = 1 + 7 + 8 + 4 = 20 bytes. Sin embargo, el tamaño de (structc_t) será de 24 bytes. Esto se debe a que, junto con los miembros de la estructura, las variables de tipo de estructura también tendrán una alineación natural. Entendámoslo con un ejemplo. Por ejemplo, declaramos una matriz de structc_t como se muestra a continuación structc_t structc_array [3];

Supongamos que la dirección base de structc_array es 0 × 0000 para cálculos fáciles. Si la estructura ocupa 20 bytes (0 × 14) como calculamos, el segundo elemento de la estructura structc_t (indexado en 1) estará en 0 × 0000 + 0 × 0014 = 0 × 0014. Es la dirección de inicio del elemento del índice 1 de la matriz. El miembro doble de esta estructura se asignará en 0 × 0014 + 0 × 1 + 0 × 7 = 0x001C (decimal 28) que no es múltiplo de 8 y está en conflicto con los requisitos de alineación de double. Como mencionamos en la parte superior, el requisito de alineación del doble es de 8 bytes. Para evitar tal desalineación, el comstackdor introducirá los requisitos de alineación en cada estructura. Será como la del miembro más grande de la estructura. En nuestro caso, la alineación de structa_t es 2, structb_t es 4 y structc_t es 8. Si necesitamos estructuras anidadas, el tamaño de la estructura interna más grande será la alineación de la estructura más grande inmediata.

En la estructura del progtwig anterior, habrá un relleno de 4 bytes después del miembro int para hacer que el tamaño de la estructura sea múltiple de su alineación. Por lo tanto, el tamaño de (structc_t) es de 24 bytes. Garantiza la alineación correcta incluso en matrices. Puedes verificar

Para evitar el relleno de la estructura! #pragma pack ( 1 ) directiva #pragma pack ( 1 ) se puede usar para organizar la memoria de los miembros de la estructura muy cerca del final de otros miembros de la estructura.

 #pragma pack(1) struct temp { int a; // size is 4 int b; // size is 4 double s; // size is 8 char ch; //size is 1 }; 

El tamaño de la estructura sería: 17

Si creamos una matriz de dicha estructura, también el primer elemento del siguiente elemento de la matriz se puede colocar en 3392515188 (base + 36) ya que es un múltiplo de 4, pero ¿por qué no sucede así?

No puede debido a los elementos double allí.

Está claro que el comstackdor y la architecture que está utilizando requieren un double para estar alineados con ocho bytes. Esto es obvio porque hay siete bytes de relleno después del char c .

Este requisito también significa que toda la estructura debe estar alineada en ocho bytes. No tiene sentido hacer que todos los double alineen con ocho bytes en relación con el inicio de la estructura si la estructura en sí está alineada solo con cuatro bytes. Por lo tanto, el relleno después de la int final para hacer sizeof(temp) un múltiplo de ocho.

Tenga en cuenta que este requisito de alineación no tiene por qué ser un requisito difícil. El comstackdor podría optar por hacer la alineación, incluso si el double s puede estar alineado por cuatro bytes, lo que podría requerir más ciclos de memoria para acceder al double si está alineado solo por cuatro bytes.