Utilice estructura de alineación y relleno en C
- Comprender los conceptos básicos de alineación y relleno en C
- Utilice la técnica de reordenación de miembros para ahorrar espacio en objetos en C
Este artículo explicará varios métodos de cómo utilizar la alineación y el relleno de struct
en C.
Comprender los conceptos básicos de alineación y relleno en C
Todos los objetos en la memoria se representan como los tipos de datos primarios como: char
, short
, int
, long
, pointer
, etc. Estos tipos de datos tienen su tamaño correspondiente en la memoria. En la mayoría de los procesadores de escritorio de 64 bits actuales, los tamaños son 1 byte para un char
, 2 bytes para un short
, 4 bytes para un int
, 8 bytes para un puntero
, y así sucesivamente. Tenga en cuenta que estos no son tamaños garantizados (excepto para char
), pero se puede recuperar el tamaño del objeto utilizando el operador sizeof
. Ahora, la alineación es el método que emplean los compiladores para colocar variables en la memoria, lo que implica que cada tipo de datos básico se almacena en la dirección divisible por el tamaño correspondiente.
Por lo general, la alineación se utiliza para acceder a los objetos de datos de forma más rápida y eficiente. La alineación obliga a declarar continuamente diferentes tipos de datos para incluir algún espacio entre sus direcciones. Es decir, si declaramos una estructura st1
con un puntero y un char
como se muestra en el siguiente ejemplo, ocupará 16 bytes en total. Sin embargo, tenga en cuenta que un solo puntero toma 8 bytes y un char
toma un byte, por lo que uno pensaría que la estructura st1
debe ocupar 9 bytes. Pero se comporta como si todos los miembros estuvieran alineados con el tamaño de miembro más grande (es decir, 8 bytes). La estructura st2
demuestra una estructura similar que ocupa la misma cantidad de memoria, excepto que tiene un array de 7 miembros char
.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
typedef struct {
char *p;
char c2;
} st1;
typedef struct {
char *p;
char c2;
char padding[7];
} st2;
printf("sizeof st1 = %zu\n", sizeof(st1));
printf("sizeof st2 = %zu\n", sizeof(st2));
exit(EXIT_SUCCESS);
}
Producción :
sizeof st1 = 16
sizeof st2 = 16
Utilice la técnica de reordenación de miembros para ahorrar espacio en objetos en C
El ejemplo anterior demuestra que hay un desperdicio de memoria cuando las estructuras incluyen diferentes tipos y no llenan los límites de alineación. Sin embargo, hay algunos casos en los que es posible reordenar los miembros de la estructura y ahorrar espacio adicional.
El siguiente código de ejemplo define la estructura foo1
que tiene el miembro más grande (char *
) en el medio y foo2
con el mismo miembro que el primero. Los tamaños de estos dos objetos son diferentes: 24 bytes y 16 bytes. Esto tiene que ver con el orden de los miembros de datos. En la estructura foo1
, p
debe alinearse en la dirección que es divisible por 8, por lo que int
y short
antes de ocupar 8 bytes en total y dos char *
s después de ocupar los 8 bytes también. Aunque, si movemos p
al primer lugar, los siguientes miembros se comprimirán en los 8 bytes y la regla de alineación también se cumplirá. Por lo tanto, el tamaño de foo2
totaliza 16 bytes y es llamado para ser empaquetado como struct
. Tenga en cuenta que el compilador gcc
tiene el especificador especial __attribute__ ((packed))
que puede forzar a empaquetarse incluso miembros de struct
no ordenados.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
typedef struct {
int n1;
short s1;
char *p;
char c1;
char c2;
} foo1;
typedef struct {
char *p;
int n1;
short s1;
char c1;
char c2;
} foo2;
typedef struct {
int n1;
short s1;
char *p;
char c1;
char c2;
} __attribute__((packed)) foo3;
printf("sizeof foo1 = %zu\n", sizeof(foo1));
printf("sizeof foo2 = %zu\n", sizeof(foo2));
printf("sizeof foo3 = %zu\n", sizeof(foo3));
exit(EXIT_SUCCESS);
}
Producción :
sizeof foo1 = 24
sizeof foo2 = 16
sizeof foo3 = 16
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook