正文
最近看到一些朋友在交流结构体对齐方面的一些问题,从他们的交谈中隐隐约感觉有几个朋友对结构体成员的对齐理解上有点偏差,不能说完全不对吧,毕竟这是老生常谈的问题了~
所以bug菌今天跟大家好好谈谈对齐这个话题~
1
变量与内存
当你随心所欲的在C程序中定义着各种变量,有没有想过他们是如何被安排到相应内存上的?
好吧,其实他们是怎么安排的,并不需要程序员太多的操心,这个映射过程都是编译器自动给大家分配的,(可以借助动态内存的角度去看待这个分配问题),因为大部分变量在一定内存区域上是可以任意选择地址的,比如你定义一个全局的int gVar 变量,在不进行特殊指定内存位置的情况下,其编译后所分配的内存地址并不一定每次都是相同的;当然,每次编译完成便会确定下来,并且程序中对该变量的访问,均会使用所确定下来的内存地址。
既然变量的地址分配过程由编译器自动完成,但有时候我们想把一些或者某个变量放在固定的内存地址处等,此时就需要通过一些语法来告诉编译器该如何分配这些指定变量内存的分配,比如要做复位数据恢复等。
然而内存的对齐问题也是对这些变量分配位置处理的一种方式,通常我们看到的align或者pack等就是来干预编译器的这块处理的。
2
结构体对齐
参考demo:
1#include <stdio.h>
2#include <stdlib.h>
3
4/*默认对齐方式*/
5typedef struct _tag_ContrlObj1
6{
7 char member1;
8 int member2;
9
10}sContrl1;
11
12/*1字节对齐*/
13#pragma pack(1)
14typedef struct _tag_ContrlObj2
15{
16 char member1;
17 int member2;
18
19}sContrl2;
20#pragma pack()
21
22/*2字节对齐*/
23#pragma pack(2)
24typedef struct _tag_ContrlObj3
25{
26 char member1;
27 int member2;
28
29}sContrl3;
30#pragma pack()
31
32/*4字节对齐*/
33#pragma pack(4)
34typedef struct _tag_ContrlObj4
35{
36 char member1;
37 int member2;
38
39}sContrl4;
40#pragma pack()
41
42/*8字节对齐*/
43#pragma pack(8)
44typedef struct _tag_ContrlObj5
45{
46 char member1;
47 int member2;
48
49}sContrl5;
50#pragma pack()
51
52int main(int argc, char *argv[]) {
53
54 printf("default:%d\n",sizeof(sContrl1));
55 printf("pack(1):%d\n",sizeof(sContrl2));
56 printf("pack(2):%d\n",sizeof(sContrl3));
57 printf("pack(4):%d\n",sizeof(sContrl4));
58 printf("pack(5):%d\n",sizeof(sContrl5));
59
60 return 0;
61}
运行结果:
1/*8字节对齐*/
2#pragma pack(8)
3typedef struct _tag_ContrlObj5
4{
5 char member1;
6 int member2;
7 char member3;
8}sContrl5;
9#pragma pack()

1/*8字节对齐*/
2#pragma pack(8)
3typedef struct _tag_ContrlObj5
4{
5 char member1;
6 double member2;
7 char member3;
8}sContrl5;
9#pragma pack()

很多朋友其实研究到这个阶段基本上就没有再继续探究了~嵌入式C语言一定要跟硬件结合理解~
3
内存对齐

最后
本文分享自微信公众号 - 嵌入式客栈(embInn)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。