Os atributos podem ser especificados com dois underscores __ antes e depois de cada palavra. O atributo que irei falar aqui é o packed, ou __packed__.
The packed attribute specifies that a variable or structure field should have the smallest possible alignment--one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.
(GCC 3.3.3 Manual)
Em tradução livre: O atributo packed especifica que uma variável ou campo de uma estrutura deve ter o mínimo de alinhamento possível -- um byte para uma variável, e um bit para um campo, a não ser que você especifique um valor maior que o atributo alinhado.
Isso significa que o GCC não vai adicionar zeros para preencher (para o alinhamento da memória), de modo que as variáveis ou campos fiquem imediatamente ao lado de cada uma. Por exemplo,
struct abc {
int a;
char b;
int c;
};
struct abc teste = {10, 20, 30};
Compilando o programa com a opção -S (compila o programa, mas não faz a montagem nem o link).
gcc -S -c sempacked.c -o sempacked.s
Olhando o arquivo gerado, sempacked.s:
.file "sempacked.c"
.globl test
.data
.align 4
.type teste, @object
.size teste, 12
teste:
.long 10
.byte 20
.zero 3
.long 30
.ident "GCC: (Gentoo 4.4.4-r2 p1.4, pie-0.4.5) 4.4.4"
.section .note.GNU-stack,"",@progbits
Veja o código em negrito. É aonde uma variável teste da estrutura é declarada. Atribuindo valores, para o campo "a" (int) como .long 10 seguido de "b" (char) como .byte 20. Para manter os campos alinhados, veja que o GCC adicionou 3 bytes com valor zero (.zero 3) antes do campo "c" (int), que foi declarado com .long 30. Isso faz com que a estrutura tenha tamanho 12 ao invés de 9, como é esperado.
struct abc {
int a;
char b;
int c;
} __attribute__((__packed__));
struct abc teste = {10, 20, 30};
E ele compilado:
.file "packed.c"
.globl teste
.data
.type teste, @object
.size teste, 9
teste:
.long 10
.byte 20
.long 30
.ident "GCC: (Gentoo 4.4.4-r2 p1.4, pie-0.4.5) 4.4.4"
.section .note.GNU-stack,"",@progbits
Agora ele não gerou o preenchimento de zeros, fazendo com que o tamanho da estrutura abc seja 9. Lembre-se que alinhamento de memória sempre é bom, mesmo que comprometa espaço, então pense duas vezes antes de usar esse atributo. Geralmente, ele é útil quando você quer atribuir a estrutura para um bloco de memória e manipular ele através dos campos da estrutura.
1 comentários:
Interessante. Não sei de nenhuma situação onde eu gostaria de manipular um bloco de memória usando um struct, mas imagino que deve servir pra algo de bem baixo nível, tipo kernel, controlar dispositivos ou coisas assim.
Postar um comentário