Na estrutura C, por que packed,aligned
parece fazer preenchimento?
Eu tenho que ler vários bytes MSB/LSB de um dispositivo remoto usando i2c. Como todos os dados do dispositivo são bytes, eu uso uint8_t
o que representa exatamente 8 bits, ou seja, 1 byte.
Agora preciso ter certeza de que a estrutura está packed
(ou seja, não há "buraco" entre os elementos na estrutura), a menos que eu não leia os dados à medida que são gerados no dispositivo remoto.
Em seguida, adicionei aligned
desempenho (ou seja, permitir que a CPU leia a estrutura com acesso mínimo à memória).
Conforme explicado aqui Preenchimento e empacotamento da estrutura , o preenchimento alinha os membros da estrutura aos limites de endereço "naturais" e o empacotamento evita o preenchimento.
Este teste simples me surpreendeu:
$ gcc --version
gcc (Debian 10.2.1-6) 10.2.1 20210110
$ cat dumb.c
#include <stdio.h>
#include <stdint.h> // uint8_t
struct struct1 {
uint8_t msb;
} __attribute__((packed));
struct struct2 {
uint8_t msb;
} __attribute__((packed,aligned(4)));
struct struct3 {
uint8_t msb;
uint8_t lsb;
} __attribute__((packed));
struct struct4 {
uint8_t msb;
uint8_t lsb;
} __attribute__((packed,aligned(4)));
int main(void) {
struct struct1 s1;
printf("sizeof(s1) %zu\n", sizeof(s1));
struct struct2 s2;
printf("sizeof(s2) %zu\n", sizeof(s2));
struct struct3 s3;
printf("sizeof(s3) %zu\n", sizeof(s3));
struct struct4 s4;
printf("sizeof(s4) %zu\n", sizeof(s4));
return 0;
}
$ gcc -o dumb dumb.c
$ ./dumb
sizeof(s1) 1
sizeof(s2) 4
sizeof(s3) 2
sizeof(s4) 4
aligned
parece "preencher o final da estrutura": isso é esperado?
- Eu esperava
s2
começar com um endereço de memória múltiplo de 4 bytes, mas ter tamanho 1. - Eu esperava
s4
começar com um endereço de memória múltiplo de 4 bytes, mas ter tamanho 2.
Eu li esses bytes de um dispositivo remoto para que cada byte seja transferido usando i2c do dispositivo para o PC: agora para desempenho, é melhor ir packed
apenas para evitar "preenchimento extra no final", ou é melhor ir packed,aligned
transferindo e lendo bytes extras "preenchidos no final" não utilizados cada vez que há uma transferência?