C语言之内存对齐

一、为什么要内存对齐

Arm对内存的访问支持字(4byte)、半字(2byte)、字节(1byte)的直接访问,但是呢他们是有一定的要求的:

  • 存取字时要求地址按字对齐,也就是地址要是4的整数倍,如0x0000、0x0004、0x0008(该地址只是举例,mcu的地址分配请参考具体手册的地址映射图)

  • 存取半字是要求地址按半字对齐,也就是地址是2的倍数,这样假如通过0x0001、0x0003这样非2倍数的地址来读取一个半字就会进入硬件中断错误

  • 存取字节简单,只要地址不超范围就可以

二、内存对齐的意义是什么?

提高内存访问速度

尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度.

现在考虑4字节存取粒度的处理器取int类型变量(32位系统),该处理器只能从地址为4的倍数的内存开始读取数据。

假如没有内存对齐机制,数据可以任意存放,现在一个int变量存放在从地址1开始的联系四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器.这需要做很多工作。但如果有内存对齐机制,那么直接从0地址读出4个字节,就可以得到数据内容。

三、内存对齐规则

  • **数据成员对齐:**成员根据其自身大小,从自身大小的整数倍内存地址(以第一个元素存储在0位置为参考)开始存储;
  • 结构体成员对齐: 首个成员从偏移量 0 开始存储。后续成员偏移地址为 min(自身对齐值, 编译器指定对齐值) 的整数倍。
  • 结构体总大小对齐: 结构体总大小需为 最大成员对齐值 的整数倍,不足时末尾填充字节。

四、如何实现内存对齐

#pragma pack(n) 作用 :强制指定对齐值为 n

cpp 复制代码
#pragma pack(1)      // 设置为1字节对齐(无填充)
struct Data {
    char a;          // 1字节 
    int b;           // 4字节(紧密排列)
};                   // sizeof = 5 
#pragma pack()       // 恢复默认对齐 

__attribute__((aligned(n))) 作用:指定结构体/变量的最小对齐值。

cpp 复制代码
struct __attribute__((aligned(8))) AlignStruct {
    char c;          // 结构体整体按8字节对齐 
    int i;
};                   // sizeof = 8(而非5)

注意:主要方式跨平台,由于不同平台编译器默认的对齐大小不同,导致硬件中断问题,例如Windows默认8字节对齐,Linux默认4字节

五、字节对齐应用场景

比如别人传输一大段数据过来,然后它默认一字节对齐,此时数据接收就会紊乱,这时候就必须强制对齐

cpp 复制代码
typedef union  __attribute__((aligned(16)))  DataPacket {  
    uint16_t raw_bytes[10];     // 原始字节访问接口 
    struct SensorData {  
        uint32_t temperature; // 温度值 (4字节)
        uint8_t status;      // 状态标志 (1字节)
        uint16_t id;         // 设备ID (2字节)
        uint8_t status2;      // 状态标志 (1字节)
        uint8_t data[3];
        uint8_t status3;      // 状态标志 (1字节)
    } sensor;
} DataPacket;
相关推荐
一只小松许️几秒前
深入理解 Rust 的内存模型:变量、值与指针
java·开发语言·rust
无限进步_22 分钟前
【C语言】寻找数组中唯一不重复的元素
c语言·开发语言·算法
JuneXcy26 分钟前
C语言易错点大总结
c语言·嵌入式硬件·算法
迎風吹頭髮2 小时前
UNIX下C语言编程与实践39-UNIX 定时器:alarm 函数与 setitimer 函数的使用与对比
服务器·c语言·unix
好开心啊没烦恼2 小时前
Python数据分析:使用爬虫从网页、社交媒体平台、论坛等公开资源提取中文和英文人名。
开发语言·爬虫·python·数据挖掘·数据分析
沐知全栈开发3 小时前
并查集基础
开发语言
egoist20233 小时前
[linux仓库]System V 进程通信详解:System V消息队列、信号量
linux·c语言·消息队列·pv·信号量
省四收割者3 小时前
Go语言入门(22)-goroutine
开发语言·vscode·后端·golang
Archie_IT3 小时前
「深入浅出」嵌入式八股文—P2 内存篇
c语言·开发语言·数据结构·数据库·c++·算法
未来之窗软件服务3 小时前
从东方仙盟筑基期看 JavaScript 动态生成图片技术-东方仙盟
开发语言·javascript·仙盟创梦ide·东方仙盟·图片技术