2013年(53)
分类: C/C++
2013-11-06 22:50:51
对内存对齐的理解:
(struct)内存对齐的规则是:
1、对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据的偏移量必须是Min(编译器被指定的对齐字节数,该数据成员的自身长度)的倍数。
GCC中,Min(系统默认(4), 数据成员自身长度(char/short/int/double))。
2、在数据成员完各自对齐之后,结构体(或联合体)本身也要进行对齐,对齐将按照编译器被指定的对齐字节数和结构体(或联合体)最大数据成员长度中,比较小的那个进行。
GCC中,Min(系统默认(4), struct成员中最大的数据类型(char/short/int/double))。
如:
1、
#include
struct abcd{
char a;
char b;
short c;
char d;
};
int main()
{
printf("sizeof(abcd)=%d/n",sizeof(struct abcd));// 运行结果:sizeof(struct abcd)=6
return 0;
}
在struct abcd 中,最大的数据类型是short型。所以在数据成员各自对齐后,整个结构体(或联合体)在进行对齐的时候,按照short型(长度为2)对齐,因为min( 4, short(2) )=2;
再看另一个代码:
2、
/*2010-09-03*/
#include
/*32位机器访问起始地址是4的倍数处的内存比较方便
min(系统默认(4),数据成员自身长度)*/
struct node1{ //sizeof(struct node1)=8;
char a1; //1
short b1; //2
int c1; //4
};
struct node2{ //sizeof(struct node2)=12;
char a2; //1
int c2; //4
short b2; //2
};
struct id_all_char{//
char id3[3]; //3
char ver; //1
char revision;//1
char flag; //1
char size[4]; //4
};
struct idid{
char id3[3];
char ver;
char revision;
char flag;
int size;
}__attribute__((packed));//__attribute__((packed))用于告诉编译器不要对其进行内存对齐!
struct all_short{//sizeof(struct all_short)=6;而不是8!因为a,b,c三个都是short,所以a,b,c最大的数据类型是short,所以min(4,2)=2(short),所以最后整个struct按照short型(长度为2)对齐
short a;//2
short b;//2
short c;//2
};
int main(void)
{
printf("sizeof(struct node1)=%d/nsizeof(struct node2)=%d/n",sizeof(struct node1),sizeof(struct node2));
printf("sizeof(struct all_short)=%d/n",sizeof(struct all_short));
printf("sizeof(struct id_all_char)=%d/n",sizeof(struct id_all_char));
printf("sizeof(struct idid)=%d/n",sizeof(struct idid));
return 0;
}
对于struct:
struct ST_DAT1
{
char cDatA;
int nDatC;
char cDatB;
} stDblChr;
struct ST_DAT2
{
char cDatA;
char cDatB;
int nDatC;
} stDblChr;
很显然,编译器在编译的时候,要做内存对齐的调整。由于两个struct中最长的变量都是int,占据了4个字节的内存空间,因此都会提升至int型。
对
ST_DAT1,cDatA紧接着是int型的nDatC,因此cDatA会自动提升成int。其实这个地方是由于分配了cDatA之后,剩下的内存空间
只有3个字节,不足以放下一个int型,要存储nDatC的时候,nDatC只有另起炉灶,放到一个新的4字节空间里面,因为cDatA自动提升成了
int。最后的cDatB,其后面没有东西了,也会自动提升成int型。因此ST_DAT1占据了12个字节(用sizeof检查)
对
ST_DAT2,cDatA,和cDatB两个写得相连,编译器,碰到cDatA,先分配一个字节给他,再碰到cDatB,由于和cDatA的数据宽度一
样,因此不会做提升,同意分配一个字节他,此时总共分配了两个字节。等编译器碰到nDatC,由于数据位宽不一样,就要做自动提升了,和前面的道理一样。
因此这个时候sizeof检查ST_DAT2占据了8个字节。