我把我公司内的bbs上面讨论的一个帖子经过整理后 ,铁道这里了。
对齐, 对于porting 工作来说实在是太重要了,
我觉得,porting的问题主要有三个大块:
1>endian问题
2〉对齐问题
3〉支持国际化的问题(也就是能否支持各种国家文字,或者说i18n)
对齐问题参考:
http://www.yuanma.org/data/2006/0723/article_1213.htm
说的太透彻了。
但是 , 里面有一句话说错了, 或者不对,
就是:
4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值
请看我后面的讨论,希望对大家有所帮助。
-----------
帖2:
这里面既有对齐上的差别,又有endian上的差别
# include < stdio. h> # include < stdlib. h> struct zlb { char a; int b; short c; } __attribute__( ( __packed__) ) ; int main( void ) { int a= 0x12345678; char * p = ( char * ) & a; short * pshort = ( short * ) ( p+ 1) ; short p2_short = 0; printf ( "*p=%#x/n" , * p) ; printf ( "*(p+3)=%#x/n" , * ( p+ 3) ) ; printf ( "*pshort=%#x/n" , * pshort) ; * pshort = 0xaabb; printf ( "modified /n" ) ; printf ( "*pshort=%#hx/n" , * pshort) ; printf ( "a=%#x/n" , a) ; printf ( "zlb size =%d/n" , sizeof ( struct zlb) ) ; return 0; }
在pc x86上的运行结果: *p=0x78 *(p+3)=0x12 *pshort=0x3456 modified *pshort=0xaabb a=0x12aabb78 zlb size =7 ------------------ 在ARM上的运行结果(Xscale ixp425 , big-endian) # # ./test *p=0x12 *(p+3)=0x78 *pshort=0x1234 //注意这里的区别,这里是关键, modified *pshort=0xaabb a=0xaabb5678 zlb size =7
-----
帖3:
struct zlb { char a; int b; short c; } __attribute__( ( __packed__) ) ;
在移植上面是不好的,也就是__packed__最好不要用。 如果要用,也要人为填充:
struct zlb { char a; char __pad1[ 3] ; int b; short c; char __pad2[ 2] ; } __attribute__( ( __packed__) ) ;
这样是比较合理的。 空间换时间,免得编译器受累。
----------
帖4:
from : http://www.yuanma.org/data/2006/0723/article_1213.htm 先让我们看四个重要的基本概念: 1.数据类型自身的对齐值: 对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。 2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。 3.指定对齐值:#pragma pack (value)时的指定对齐值value。 4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。 有 了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是 表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数 据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数 倍
------------ 上面这句话本身来讲,没有什么问题,但是 似乎这句有问题:“4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。” 应该改为 "有效对齐值是自身对齐值和指定对齐值中大的那个 " 显然应该是大的那个 。 为此专门验证了一下 : 注意: #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 就是计算偏移的, 这样才好知道编译器是如何存放我们的变量的。
# include < stdio. h> # include < stdlib. h> //consider struct aligned # define offsetof ( TYPE, MEMBER) ( ( size_t ) & ( ( TYPE * ) 0) - > MEMBER) struct zlb { char a; //0 int b; //4 short c ; //8 int d; //12 short e; //16 } __attribute__( ( aligned( 8) ) ) ; //24 ,最后的有效的对齐值应该是 8 (8(指定对齐值) > 4(结构体自身对齐值) ) ,所以 总字节数是 8的倍数 。 可以从下面的结构体来验证, 看看 struct zlb 的放置位置 , 是不是 8 ,便可验证。 struct bob { int a ; // 0 struct zlb zlb_s; // 8 short b; //32 char c; //34 } __attribute__( ( aligned( 16) ) ) ; //total : 48 //}__attribute__((__packed__)); int main( void ) { printf ( "size of zlb = %d/n" , sizeof ( struct zlb) ) ; printf ( "offset a=%d/n" , offsetof ( struct zlb, a) ) ; printf ( "offset b=%d/n" , offsetof ( struct zlb, b) ) ; printf ( "offset c=%d/n" , offsetof ( struct zlb, c) ) ; printf ( "offset d=%d/n" , offsetof ( struct zlb, d) ) ; printf ( "offset e=%d/n" , offsetof ( struct zlb, e) ) ; printf ( "/n/n" ) ; printf ( "size of bob struct =%d/n" , sizeof ( struct bob) ) ; printf ( "offset a=%d/n" , offsetof ( struct bob, a) ) ; printf ( "offset struct zlb=%d/n" , offsetof ( struct bob, zlb_s) ) ; printf ( "offset b=%d/n" , offsetof ( struct bob, b) ) ; printf ( "offset c=%d/n" , offsetof ( struct bob, c) ) ; // printf("size of tt struct =%d/n",sizeof(struct tt)); return 0; }
执行结果: pc x86 (arm上也是如此) size of zlb = 24 offset a=0 offset b=4 offset c=8 offset d=12 offset e=16 size of bob struct =48 offset a=0offset struct zlb=8 //怎么样? 确实是 8 ,而不是 4吧? 所以作者的话错了。 结构体的有效对齐值应该是 结构体自身对齐值和 指定对齐值(或默认对齐值)较大的那个 offset b=32 offset c=34