数据对齐
原理简述
PC 实验
这边使用的环境为 intel i7, windows 7 ,对齐问题未影响操作结果,只对操作性能有所影响,windows 操作系统下即便不考虑对齐问题,依然可以编译运行成功。
|
|
运行结果: 1.230000
MCU 下
MCU 选用 efm32hgxx 和 stm32f4xx 两款不同的芯片,对齐问题均会影响程序的实际运行。
错误代码:
|
|
错误结果:
|
|
分析可知,问题出在 &arr[3] 地址为 0x20000003,不为 4 的整数倍,不对齐,MCU 无法正确将该段地址解析成 float 等类型。解决这类问题,我们可以用 __align(x)
函数强制要求起始位置对齐,__align(4)
可以让变量对齐到 4 的整数倍地址。
ARM 下的对齐
使用 __align(num)
可以强制让数据或类型对齐,这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时就要用到此命令align(8)进行修饰限制,来保证数据对象是相应对齐。这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节对齐,但是不能让4字节的对象2字节对齐。align是存储类修改,他只修饰最高级类型对象,不能用于结构或者函数对象。
比如:__align(4) u8 mem1base[MEM1_MAX_SIZE];//保证分配的数组空间4字节对齐,同时保证数组首地址可被4整除
|
|
ARM 一字节对齐
packed
packed是进行一字节对齐
1.不能对 packed 的对象进行对齐
2.所有对象的读写访问都进行非对齐访问
3.float及包含float的结构联合及未用packed的对象将不能字节对齐
4.packed对局部整形变量无影响
5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定义为packed。__packed int* p; //__packed int 则没有意义
6.对齐或非对齐读写访问带来问题
|
|
注意:对于上述 char 类型转换为 float,无法通过 packed 执行,因为 packed 无法对 float 操作,而如果是 32 位整型则可以通过 __packed 来字节对齐。