Win32平台下的微软C编译器(cl.exe for 80x86)在默认情况下采用如下的对齐规则: 任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而 char类型数据(1字节)则可以从任何一个地址开始。Linux下的GCC奉行的是另外一套规则(在资料中查得,并未验证,如错误请指正):任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数。
ANSI C规定一种结构类型的大小是它所有字段的大小以及字段之间或字段尾部的填充区大小之和。填充区就是为了使结构体字段满足内存对齐要求而额外分配给结构体的空间。那么结构体本身有什么对齐要求吗?有的,ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松,可以更严格(但此非强制要求,VC7.1就仅仅是让它们一样严格)。
__attribute__((packed))意思是按最小对齐,也就是单字节。__attribute__((aligned(n)))是指按n字节对齐,这里的对齐不仅指起始位置n字节对齐,也指的结束的位置也是n字节对齐。对于结构来说,例如:
struct E{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(8)));
结构内部的成员按照自己的对齐方式,而该结构的起始和结束位置都要8字节对齐,所以a占4字节,b占4字节,c占4字节,d占4字节,e占8字节,f占8字节(为了结束位置对齐),总共占32字节。
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(8)));
结构内部的成员按照自己的对齐方式,而该结构的起始和结束位置都要8字节对齐,所以a占4字节,b占4字节,c占4字节,d占4字节,e占8字节,f占8字节(为了结束位置对齐),总共占32字节。
struct E{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(4)));
a占4字节,b占4字节,c占4字节,d占4字节,e占8字节,f占4字节,共28字节。
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(4)));
a占4字节,b占4字节,c占4字节,d占4字节,e占8字节,f占4字节,共28字节。
但是:
struct E{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(1)));
也是占用28字节,怎样解释?可能,"ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松",这个条件的优先级更高。它屏蔽了__attribute__((aligned(1)))这个条件。(注意该处编译器是GCC,处理器认为是arm,"Linux下的GCC奉行的是另外一套规则(在资料中查得,并未验证,如错误请指正):任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数")。
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(1)));
也是占用28字节,怎样解释?可能,"ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松",这个条件的优先级更高。它屏蔽了__attribute__((aligned(1)))这个条件。(注意该处编译器是GCC,处理器认为是arm,"Linux下的GCC奉行的是另外一套规则(在资料中查得,并未验证,如错误请指正):任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数")。
而例如#pragma pack(1) ,则应该是对所有数据类型的对齐吧!
没有评论:
发表评论