在C结构体中,为什么packed,aligned似乎是在做填充?

问题描述 投票:0回答:1

在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
每次传输时传输和读取额外未使用的“末尾填充”字节?

c gcc struct padding packing
1个回答
0
投票

aligned
声明上的
struct
属性意味着结构体的任何实例都必须从对齐的地址开始。

这也意味着,如果您有一个结构数组,该结构可能需要尾部填充,以便数组的每个成员正确对齐。

虽然

packed
属性将最小化结构中使用的任何填充,但与
aligned
结合使用时,不一定完全消除此类填充。

© www.soinside.com 2019 - 2024. All rights reserved.