微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM字节对齐问题详解

ARM字节对齐问题详解

时间:11-09 来源:互联网 点击:

此肯定是对齐的,之所以在后面补充2个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结构B的数组,那么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为4的整数倍,那么下一个结构的起始地址将是0x0A,这显然不能满足结构的地址对齐了,因此我们要把结构补充成有效对齐大小的整数倍.其实诸如:对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,这些已有类型的自身对齐值也是基于数组考虑的,只是因为这些类型的长度已知了,所以他们的自身对齐值也就已知了.

同理,分析上面例子C: #pragma pack (2) /*指定按2字节对齐*/ struct C { char b; int a; short c; }; #pragma pack () /*取消指定对齐,恢复缺省对齐*/ 第 一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0开始,那么b存放在0x0,符合0x0%1=0;第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x2、0x3、0x4、0x5四个连续字节中,符合0x2%2=0。第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放 在0x6、0x7中,符合0x6%2=0。所以从0x0到0x07共八字节存放的是C的变量。又C的自身对齐值为4,所以C的有效对齐值为2。又8%2=0,C只占用0x0到0x7的八个字节。所以sizeof(struct C)=8.

四.如何修改编译器的默认对齐值?

1.在VC IDE中,可以这样修改:[Project][Settings],c/c++选项卡Category的Code Generation选项的StructMember Alignment中修改,默认是8字节。 2.在编码时,可以这样动态修改:#pragma pack .注意:是pragma而不是progma.

五.针对字节对齐,我们在编程中如何考虑?

如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做法是显式的插入reserved成员: struct A{ char a; char reserved[3];//使用空间换时间 int b; }

reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.

六.字节对齐可能带来的隐患:

代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。例如: unsigned int i = 0x12345678; unsigned char *p=NULL; unsigned short *p1=NULL; p=&i; *p=0x00; p1=(unsigned short *)(p+1); *p1=0x0; 最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。 在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐.

七.如何查找与字节对齐方面的问题:

如果出现对齐或者赋值问题首先查看 1. 编译器的big little端设置 2. 看这种体系本身是否支持非对齐访问 3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。

八.相关文章:转自http://blog.csdn.net/goodluckyxl/archive/2005/10/17/506827.aspx

ARM下的对齐处理from DUI0067D_ADS1_2_CompLib3.13 type qulifiers有部分摘自ARM编译器文档对齐部分 对齐的使用:

1.__align(num) 这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时 就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。 这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节 对齐,但是不能让4字节的对象2字节对齐。 __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。

2.__packed __packed是进行一字节对齐

1.不能对packed的对象进行对齐

2.所有对象的读写访问都进行非对齐访问

3.float及包含float的结构联合及未用__packed的对象将不能字节对齐

4.__packed对局部整形变量无影响

5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定义为packed。 __packed int* p; //__packed int 则没有意义

6.对齐或非对齐读写访问带来问题

__packed struct STRUCT_TEST { char a; int b; char c; } ; //定义如下结构此时b的起始地址一定是不对齐的

//在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]

//将下面

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top