vectores reservar que memoria dinamica crear con como arreglo array administracion c++ c memory-alignment structure-packing

c++ - reservar - Alineación de la memoria en C-estructuras



que es la memoria dinamica en c (10)

Al menos en la mayoría de las máquinas, un tipo solo se alinea siempre con un límite tan grande como el tipo [Editar: realmente no puede exigir una alineación "más" que esa, porque debe poder crear matrices, y no se puede insertar el relleno en una matriz]. En su implementación, short es aparentemente 2 bytes e int 4 bytes.

Eso significa que su primera estructura está alineada con un límite de 2 bytes. Como todos los miembros tienen 2 bytes cada uno, no se inserta ningún relleno entre ellos.

El segundo contiene un elemento de 4 bytes, que se alinea con un límite de 4 bytes. Dado que está precedido por 6 bytes, se insertan 2 bytes de relleno entre v3 i , lo que da 6 bytes de datos en el short s, dos bytes de relleno y 4 bytes más de datos en la int para un total de 12.

Estoy trabajando en la máquina de 32 bits, así que supongo que la alineación de la memoria debería ser de 4 bytes. Di que tengo la estructura

typedef struct { unsigned short v1; unsigned short v2; unsigned short v3; } myStruct;

el tamaño real es de 6 bytes, y supongo que el tamaño alineado debería ser 8, pero sizeof(myStruct) me devuelve 6.

Sin embargo si escribo:

typedef struct { unsigned short v1; unsigned short v2; unsigned short v3; int i; } myStruct;

el tamaño real es 10 bytes, alineado es 12, y esta vez sizeof(myStruct) == 12 .

¿Alguien puede explicar cuál es la diferencia?


Asumiendo:

sizeof(unsigned short) == 2 sizeof(int) == 4

Entonces yo personalmente usaría lo siguiente (su compilador puede diferir):

unsigned shorts are aligned to 2 byte boundaries int will be aligned to 4 byte boundaries. typedef struct { unsigned short v1; // 0 bytes offset unsigned short v2; // 2 bytes offset unsigned short v3; // 4 bytes offset } myStruct; // End 6 bytes. // No part is required to align tighter than 2 bytes. // So whole structure can be 2 byte aligned. typedef struct { unsigned short v1; // 0 bytes offset unsigned short v2; // 2 bytes offset unsigned short v3; // 4 bytes offset /// Padding // 6-7 padding (so i is 4 byte aligned int i; // 8 bytes offset } myStruct; // End 12 bytes // Whole structure needs to be 4 byte aligned. // So that i is correctly aligned.


Cada tipo de datos debe alinearse en un límite de memoria de su propio tamaño. Por lo tanto, un short debe estar alineado en un límite de 2 bytes, y un int debe estar en un límite de 4 bytes. De manera similar, un long long tendría que estar en un límite de 8 bytes.


El estándar no dice mucho sobre el diseño de estructuras con tipos completos, depende del compilador. Decidió que necesita el int para comenzar en un límite para acceder a él, pero como tiene que hacer direccionamiento de memoria de límite inferior para los cortos, no es necesario rellenarlos.


En primer lugar, mientras que los detalles del relleno se dejan en manos del compilador, el sistema operativo también impone algunas reglas en cuanto a los requisitos de alineación. Esta respuesta asume que estás usando gcc, aunque el sistema operativo puede variar

Para determinar el espacio ocupado por una estructura dada y sus elementos, puedes seguir estas reglas:

Primero, suponga que la estructura siempre comienza en una dirección que está correctamente alineada para todos los tipos de datos.

Luego para cada entrada en la estructura:

  • El espacio mínimo necesario es el tamaño bruto del elemento dado por sizeof(element) .
  • El requisito de alineación del elemento es el requisito de alineación del tipo base del elemento. En particular, esto significa que el requisito de alineación para una matriz char[20] es el mismo que el requisito para una función simple.

Finalmente, el requisito de alineación de la estructura en su conjunto es el máximo de los requisitos de alineación de cada uno de sus elementos.

gcc insertará relleno después de un elemento dado para asegurar que el siguiente (o la estructura si estamos hablando del último elemento) esté alineado correctamente. Nunca reorganizará el orden de los elementos en la estructura, incluso si eso ahorrará memoria.

Ahora los requisitos de alineación en sí también son un poco extraños.

  • Linux de 32 bits requiere que los tipos de datos de 2 bytes tengan una alineación de 2 bytes (sus direcciones deben ser pares). Todos los tipos de datos más grandes deben tener una alineación de 4 bytes (las direcciones terminan en 0x0 , 0x4 , 0x8 o 0xC ). Tenga en cuenta que esto también se aplica a tipos de más de 4 bytes (como double y long double ).
  • Windows de 32 bits es más estricto porque si un tipo tiene un tamaño de K bytes, debe estar alineado con K bytes. Esto significa que un double solo puede colocarse en una dirección que termina en 0x0 o 0x8 . La única excepción a esto es el long double que todavía está alineado en 4 bytes, aunque en realidad tiene una longitud de 12 bytes.
  • Tanto para Linux como para Windows, en máquinas de 64 bits, un tipo de K bytes debe estar alineado con K bytes. Nuevamente, el long double es una excepción y debe estar alineado a 16 bytes.

En su primera estructura, ya que cada elemento es de tamaño short , toda la estructura se puede alinear en límites short , por lo que no es necesario agregar ningún relleno al final.

En la segunda estructura, el int (probablemente 32 bits) debe alinearse con la palabra para que inserte el relleno entre v3 e i para alinear i .


La razón por la que el segundo sizeof(myStruct) es 12 es el relleno que se inserta entre v3 i para alinear i en un límite de 32 bits. Hay dos bytes de eso.

Wikipedia explica el relleno y la alineación con bastante claridad.


Olvídese de tener miembros diferentes, incluso si escribe dos estructuras cuyos miembros son exactamente iguales, con una diferencia es que el orden en el que se declaran es diferente, entonces el tamaño de cada estructura puede ser (y con frecuencia es) diferente.

Por ejemplo, ver esto,

#include <iostream> using namespace std; struct A { char c; char d; int i; }; struct B { char c; int i; //note the order is different! char d; }; int main() { cout << sizeof(A) << endl; cout << sizeof(B) << endl; }

Compílalo con gcc-4.3.4 , y obtendrás esta salida:

8 12

Es decir, los tamaños son diferentes, aunque ambas estructuras tienen los mismos miembros.

Código en Ideone: http://ideone.com/HGGVl

La conclusión es que el Estándar no habla sobre cómo se debe hacer el relleno, por lo que los compiladores son libres de tomar cualquier decisión y no puede asumir que todos los compiladores tomen la misma decisión.


Por defecto, los valores se alinean de acuerdo a su tamaño. Así que un valor de 2 bytes como un short se alinea en un límite de 2 bytes, y un valor de 4 bytes como un int se alinea en un límite de 4 bytes

En su ejemplo, se agregan 2 bytes de relleno antes de i para garantizar que caiga en un límite de 4 bytes.

(Toda la estructura se alinea en un límite al menos tan grande como el valor más grande de la estructura, por lo que su estructura se alineará con un límite de 4 bytes).

Las reglas reales varían según la plataforma: la página de Wikipedia sobre la alineación de la estructura de datos tiene más detalles.

Los compiladores generalmente le permiten controlar el empaque a través de (por ejemplo) #pragma pack directivas #pragma pack .


Suena como si se alineara con las bounderies según el tamaño de cada var, de modo que la dirección es un múltiplo del tamaño al que se accede (por lo tanto, los cortos se alinean a 2, los ints se alinean a 4, etc.) el int, sizeof(mystruct) debe ser 10. Por supuesto, todo depende del compilador que se esté utilizando y de la configuración que esté utilizando.