在 C 结构中,为什么packed,aligned
似乎要做填充?
我必须使用 i2c 从远程设备读取一堆 MSB/LSB 字节。由于所有设备数据都是字节,因此我使用uint8_t
它来精确表示 8 位,即 1 个字节。
现在我需要确保结构是packed
(即结构中的元素之间没有“洞”),除非我不会读取远程设备中生成的数据。
然后,我添加了aligned
性能(即允许 CPU 以最少的内存访问读取结构)。
正如结构填充和打包所解释的,填充将结构成员与“自然”地址边界对齐,而打包可防止填充。
这个简单的测试让我很惊讶:
$ 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
似乎“填充了结构的末尾”:这是预期的结果吗?
- 我希望
s2
从 4 字节的倍数内存地址开始,但大小为 1。 - 我希望
s4
从 4 字节的倍数内存地址开始,但大小为 2。
我从远程设备读取这些字节,因此每个字节都使用 i2c 从设备传输到 PC:现在为了提高性能,最好packed
只避免“末尾的额外填充”,还是最好packed,aligned
每次传输时都传输和读取额外未使用的“末尾填充”字节?