STM32F4系列MCU非字节对齐访问相关技术疑问咨询
非字节对齐访问问题解答
1. 为何代码执行非字节对齐访问操作时系统未出现崩溃?
你的代码里虽然给结构体加了__attribute__((packed))让d成员处于非4字节对齐的偏移位置,但实际运行没崩溃的原因主要有三点:
- ARM架构支持非对齐访问:ARMv6及之后的架构默认允许用户空间的非对齐内存访问,相关指令(如非对齐的
LDR/STR)不会触发数据中止异常;只有ARMv5及更早的老架构才会强制要求对齐,非对齐访问才会崩溃。 - 编译器自动适配:ARMCC遇到
packed结构体的非对齐成员时,会自动生成适配非对齐访问的指令序列——要么用多字节加载拼接的方式处理,要么调用架构支持的非对齐访问指令,避免触发异常。 - 当前代码的操作场景:你只是给
aaa.d赋值,没有涉及到依赖对齐的复杂操作(比如某些需要对齐地址的协处理器指令、或者对非对齐地址的批量操作),所以没有触发异常的条件。
补充:你代码里的aaa是栈上的局部变量,ARMCC默认会保证栈的4字节对齐,所以aaa的起始地址是4字节对齐的,d成员的地址是起始地址+3,确实是非4字节对齐的,但上述原因让这次访问没有崩溃。
2. unsigned char buff变量的起始地址在何种情况下会是2的倍数而非4的倍数?
unsigned char类型本身最小对齐要求是1字节,但ARMCC默认对全局变量采用4字节对齐。要让buff的起始地址是2的倍数但不是4的倍数,可通过以下几种方式实现:
- 调整编译器对齐选项:修改ARMCC编译参数,将全局变量的默认对齐设置为2字节(比如使用
--align 2选项,具体参数需对应你的ARMCC版本),此时全局变量会按2字节对齐,只要前面的全局变量总占用字节数是偶数但不是4的倍数,buff的地址就会是2的倍数而非4的倍数。 - 利用前置变量的非对齐布局:在
buff之前定义全局变量,同时通过__attribute__((packed))禁止编译器自动填充对齐。比如:
这里__attribute__((packed)) struct { unsigned char a; unsigned char b; } pre_data; unsigned char buff[100];pre_data是packed结构体,占用2字节,若pre_data的起始地址是4的倍数,那buff的起始地址就是&pre_data + 2,也就是4n+2,满足是2的倍数但非4的倍数的要求。 - 自定义链接脚本布局:通过链接脚本指定
buff所在段的起始地址为2的倍数但非4的倍数,链接器会直接将buff放置到指定地址,实现需求。
内容的提问来源于stack exchange,提问作者kanghao chen
相关产品推荐
相关产品推荐

