0%

结构体的内存对齐与协议

在C语言里一种有效组织数据的方式就是结构体,除了储存多种类型的数据外,结构体也是使用一个协议的数据格式最好的办法。这样做还有一个好处就是上位机采用同样的结构体即可通信,在代码层面的移植相当容易。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct{
int a,b;
char c;
float f;
}data_t;

data_t bundle;
//给各个数值输入值
bundle.a = 1;
bundle.b = 2;
bundle.c = 'a';
bundle.f = 0.0f;
//此处采用转换指针类型的形式调用如串口等发送数据
uart_send((unsigned char*)&bundle);

然而有个问题,结构体内部的变量并不是紧密的排在一起,他们中间默认是有空隙的。在上面的代码中sizeof(data_t)的值并不是4+4+1+4,而是在char c后面增加了三个字节的空位。这就是内存对齐的问题,本质的原因是硬件上为了减少访问次数,通常会将变量按照4字节对齐。

通俗一点的解释办法,这个原则就是要求单个变量不能跨4字节(当然双精度对于这个原则不适用,但对于四字节及四字节以下的变量,这个原则却是正确的)。那么有没有变量连续储存的结构体呢?由于内存对齐实际上是编译器的优化,而不是硬件的强制要求,所以我们可以配置编译器让它在以牺牲访问次数的代价来换取这种对齐模式。参照编译器手册,我们可以利用#pragma pack(1)来完成或者在struct前加__PACKED

参考:https://zhuanlan.zhihu.com/p/30007037