【C】结构体的内存对齐

内存对齐的作用:

1、不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取特定类型的数据,否则抛出硬件异常(可参考【培训】考试试题1)。

2、数据结构尤其是栈,应该尽可能的在自然边界上对齐,可以让处理器尽可能的只做一次访问。

char、int、double等基础变量类型的自然对齐原则

变量地址能够被类型大小整除

数组的自然对齐原则

按数组元素的类型处理

struct自然对齐的3个原则

1、结构体变量的起始地址能够被其最宽成员类型大小整除,第一个成员地址一定等于起始地址;

2、结构体每个成员相对于起始地址的偏移能够被其自身类型大小整除,如果不能则在前一个成员后面补充字节;

3、结构体总体大小能够被最宽成员类型大小整除,如不能则在后面补充字节;

注意:如果程序中有#pragma pack(n)预编译指令,对于第1和第3原则,取n和结构体内最宽成员类型大小中的最小值作为对齐标准,用"对齐标准"替换原则中的"最宽成员类型大小"。对于第2原则,取n和每个成员自身类型大小中的最小值作为对齐标准,用"对齐标准"替换原则中的"自身类型大小"。

举例:

复制代码
struct S 
{
    char c;
    int i;
};

sizeof(struct S)为8

复制代码
struct S 
{
    double d;
    char c;
    int i;
    short s;
};        

sizeof(struct S)为24

复制代码
#pragma pack(1)
struct S 
{
    char c;
    int i;
};
#pragma pack()

sizeof(struct S)为5

复制代码
#pragma pack(4)
struct S 
{
    char c[3];
    short s;
};
#pragma pack()   

sizeof(struct S)为6,char c3虽然整体大小占3直接,但是每个成员还是1字节,结构体里最大成员单位是2字节,整个结构体对齐到2的整数倍。如果c是一个3字节大小结构体,结果不变,结构体大小不属于成员类型。

结构体字节对齐意义:

将一个结构体数据拷贝到一段字节缓存中,用偏移去取数据,如果结构体字节不对齐就会出问题,可以用#pragma pack(1)去修饰。在使用这种方法的时候,对于结构体里uint8_t可以直接访问,但是对于uint16_t及以上,必须用单字节拆解拼合的方式去读写,不能直接使用,寄存器地址之类的必须对齐使用。补充:如果编译优化等级不是-O0,一般的编译器会优化这种非对齐结构体,实际汇编码是单字节访问,同时对于奇地址不能强转,强转的话优化效果会消失。总结就是非对齐结构体的变量可以直接使用,但是不能把一个奇地址赋值或强转成一个偶地址指针,再使用这个指针处理变量。

union自然对齐的3个原则

1、联合体变量的起始地址能够被其最宽成员类型大小整除;

2、联合体每个成员相对于起始地址的偏移都是0;

3、联合体总体大小能够被最宽成员类型大小整除,如不能则在后面补充字节;

复制代码
union U
{
    double d;
    int i[5];
    char c;
};

sizeof(union U)为24

堆栈内存对齐( 全局或静态数据直接按自然对齐即可****)****

  1. 堆栈区的起始地址由编译器强制对齐到8字节(启动或者链接文件中配置),(UCOS上线程栈没有对齐到8字节就会出现浮点数打印异常);
  2. AAPCS(Procedure Call Standard for the Arm Architecture)规范要求栈在任何时候都保持4字节对齐,在函数调用入口点保持8字节对齐。这意味着在调用函数时,栈指针必须是8字节对齐的。但是如果某个空函数没有用栈空间,编译器会优化成4字节对齐,减少压栈(函数调用等于压栈,函数返回等于出栈,压栈==入栈,弹栈==出栈)。
  3. 中断入口函数的栈顶地址可以通过SCB(有的是NVIC)中的STKALIGN置位来对齐到8字节,如果压栈时减4字节,出栈时会自动再加4字节(栈区是由高到低,向下生长)。
  4. 局部变量的对齐原则为自然对齐,(AC5下所有局部变量地址强制对齐到4字节);
相关推荐
雪碧透心凉_28 分钟前
while 循环与循环嵌套
开发语言·python
乐观勇敢坚强的老彭35 分钟前
信奥C++一维数组笔记
开发语言·c++·笔记
变量未定义~39 分钟前
最小生成树1(Prim模板)、最小生成树2(kruskal模板)、最近公共祖先(模板)
算法
这就是佬们吗43 分钟前
Python入门⑤-异常处理、文件操作与实战项目
开发语言·数据库·python·算法·pycharm
LONGZETECH1 小时前
新能源汽车充电设备装配与调试仿真教学软件 技术架构与核心实现解析
大数据·算法·3d·unity·架构·汽车
自学小白菜1 小时前
关于提升机器学习算法做预测回归任务精度的方法分享
算法·机器学习·回归·提升精度
asdzx671 小时前
Python PDF 拆分实战指南:单页拆分与按需页码范围拆分
开发语言·python·pdf
C++ 老炮儿的技术栈1 小时前
基于MFC+原生GDI手动自绘仪表盘控件
c语言·c++·visual studio·控件·工业控制·gdi·自绘
学废了wuwu1 小时前
从入门到实战:深入浅出模型压缩三大核心——剪枝、彩票假设与知识蒸馏
人工智能·算法·剪枝
孬甭_1 小时前
C++ vector
开发语言·c++