La mayoría de los compiladores alinearán automáticamente los valores de datos al tamaño de palabra de la plataforma, o al tamaño del tipo de datos, el que sea más pequeño. La gran mayoría de los procesadores de consumo y empresariales usan un tamaño de palabra de 32 bits. (Incluso los sistemas de 64 bits generalmente usan 32 bits como tamaño de palabra nativo)
Como tal, el orden de los miembros en su estructura podría desperdiciar algo de memoria. En tu caso específico, estás bien. Voy a añadir en los comentarios de la huella real de memoria utilizada:
typedef struct structc_tag{
char c; // 1 byte
// 3 bytes (padding)
double d; // 8 bytes
int s; // 4 bytes
} structc_t; // total: 16 bytes
Esta regla se aplica a estructuras demasiado, por lo que incluso si los reorganizado por lo que el campo más pequeño fue el último, a pesar de ello tiene una estructura del mismo tamaño (16 bytes).
typedef struct structc_tag{
double d; // 8 bytes
int s; // 4 bytes
char c; // 1 byte
// 3 bytes (padding)
} structc_t; // total: 16 bytes
Si se va a declarar más campos que eran más pequeños de 4 bytes, se podía ver algunas reducciones de memoria si se agrupan por tamaño. Por ejemplo:
typedef struct structc_tag{
double d1; // 8 bytes
double d2; // 8 bytes
double d3; // 8 bytes
int s1; // 4 bytes
int s2; // 4 bytes
int s3; // 4 bytes
short s4; // 2 bytes
short s5; // 2 bytes
short s6; // 2 bytes
char c1; // 1 byte
char c2; // 1 byte
char c3; // 1 byte
// 3 bytes (padding)
} structc_t; // total: 48 bytes
Declarar una estructura estúpida podría perder una gran cantidad de memoria, a no ser que el compilador reordena los elementos (que, en general, no lo hará, sin ser explícitamente dicho a)
typedef struct structc_tag{
int s1; // 4 bytes
char c1; // 1 byte
// 3 bytes (padding)
int s2; // 4 bytes
char c2; // 1 byte
// 3 bytes (padding)
int s3; // 4 bytes
char c3; // 1 byte
// 3 bytes (padding)
} structc_t; // total: 24 bytes
// (9 bytes wasted, or 38%)
// (optimal size: 16 bytes (1 byte wasted))
Los dobles son mayores que 32 bits, y por lo tanto de acuerdo con la regla en la primera sección, están alineados a 32 bits. Alguien mencionó una opción del compilador que cambia la alineación, y que la opción del compilador predeterminado es diferente entre los sistemas de 32 y 64 bits, esto también es válido. Entonces, la verdadera respuesta sobre los dobles es que depende de la plataforma y el compilador.
El rendimiento de la memoria se rige por palabras: la carga desde la memoria ocurre en etapas que dependen de la ubicación de los datos. Si los datos cubren una palabra (i.mi. es palabra alineada), solo esa palabra necesita ser cargada. Si no está alineado correctamente (es decir, un int en 0x2), el procesador debe cargar 2 palabras para leer correctamente su valor. Lo mismo se aplica a los dobles, que normalmente ocupan 2 palabras, pero si no están alineados, retírenlos 3. En sistemas de 64 bits donde es posible la carga nativa de cantidades de 64 bits, se comportan como 32 bits en sistemas de 32 bits si están correctamente alineados , que se pueden recuperar en una sola pasada, pero por lo demás, requerirán 2.
Alineación es la implementación definida, por lo que tiene poco sentido hacer esta pregunta de manera general. Debe elegir un compilador/plataforma específico para preguntar. –
En realidad obtengo 24 bytes ... –
También hay 4 bytes de relleno al final para asegurar que el doble aún esté alineado en los elementos de una matriz de estas estructuras. Generalmente. –