Use o alinhamento e preenchimento da estrutura em C
- Compreender os princípios básicos de alinhamento e preenchimento em C
- Use a técnica de reordenação de membros para economizar espaço em objetos em C
Este artigo irá explicar vários métodos de como usar o alinhamento e preenchimento struct
em C.
Compreender os princípios básicos de alinhamento e preenchimento em C
Todos os objetos na memória são representados como os tipos de dados primários como: char
, short
, int
, long
, pointer
etc. Esses tipos de dados têm seus tamanhos correspondentes na memória. Na maioria dos processadores de desktop de 64 bits contemporâneos, os tamanhos são 1 byte para um char
, 2 bytes para um short
, 4 bytes para um int
, 8 bytes para um ponteiro
e assim por diante. Observe que esses não são tamanhos garantidos (exceto para char
), mas pode-se recuperar o tamanho do objeto usando o operador sizeof
. Agora, alinhamento é o método que os compiladores empregam para colocar variáveis na memória, o que implica que cada tipo de dado básico é armazenado no endereço divisível pelo tamanho correspondente.
Normalmente, o alinhamento é utilizado para acessar objetos de dados de forma mais rápida e eficiente. O alinhamento força a declaração contínua de diferentes tipos de dados para incluir algum espaçamento entre seus endereços. Ou seja, se declararmos uma estrutura st1
com um ponteiro e um char
como mostrado no exemplo a seguir, ela ocupará 16 bytes no total. Lembre-se, porém, de que um único ponteiro ocupa 8 bytes e um char
ocupa um byte, então alguém poderia pensar que a estrutura st1
deve ocupar 9 bytes. Mas se comporta como se todos os membros estivessem alinhados com o tamanho do maior membro (ou seja, 8 bytes). A estrutura st2
demonstra uma estrutura semelhante que ocupa a mesma quantidade de memória, exceto que tem um array de 7 membros 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);
}
Resultado:
sizeof st1 = 16
sizeof st2 = 16
Use a técnica de reordenação de membros para economizar espaço em objetos em C
O exemplo anterior demonstra que há algum desperdício de memória quando as estruturas incluem tipos diferentes e não preenchem os limites do alinhamento. No entanto, existem alguns casos em que pode ser possível reordenar os membros da estrutura e economizar espaço extra.
O próximo código de exemplo define a estrutura foo1
que possui o maior membro (char *
) no meio e foo2
com o mesmo membro do primeiro. Os tamanhos desses dois objetos são diferentes - 24 bytes e 16 bytes. Isso tem a ver com a ordem dos membros de dados. Na estrutura foo1
, p
precisa ser alinhado no endereço que é divisível por 8, então o int
e o short
antes de ocupar 8 bytes no total e dois char *
s depois de ocupar os 8 bytes também. Embora, se movermos p
para o primeiro lugar, os membros seguintes serão espremidos nos 8 bytes e a regra de alinhamento também será satisfeita. Assim, o tamanho de foo2
totaliza 16 bytes e é chamado para ser empacotado como struct
. Observe que o compilador gcc
tem o especificador especial __atributo__ ((embalado))
que pode forçar até mesmo membros struct
não ordenados a serem empacotados.
#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);
}
Resultado:
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