内存字节对齐
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.内存字节对齐和小端模式:
/*
本程序是关于:编译器内存的字节对齐方式和存储时的小端对齐模式(win7 32bit)
#pragma pack(n)
默认为8字节对齐,(即n=8)其中n的取值为1,2,4,8,16,32等
内存字节对齐大小和方式:
1)结构体内变量对齐:
每个变量的对齐字节数大小argAlignsize=min(#pragma pack(n),sizeof(变量));
方式:结构体的第一个变量的初始偏移地址为0,其它变量的偏移地址(当前变量的起始地址)必须是argAlignsize的整数倍,不够整数倍的补空,不添加任何数据
2)结构体对齐:
结构体的对齐字节数大小strAlignsize=min(#pragma pack(n),sizeof(所有变量中最大字节的变量))
方式:
A.对于单独的结构体来说,结构体本身按照strAlignsize大小来对齐
B.结构体B在结构体A中时,结构体B的起始地址是结构体B的
strAlignsize大小的整数倍
小端对齐模式:
指针指着一个存储空间,存储空间地址由低到高的存储内容为:0x78,0x67,0x33,0x45
若指针为char,则获取的数据为0x78
若指针为short,则获取的数据为0x6778
若指针为long,则获取的数据为0x45336778
*/
#include
using namespace std;
/*更改C编译器内存的缺省字节对齐方式,由默认的n=4字节,变为n字节对齐,其中n的取值为1,2,4,8,16,32等*/
#pragma pack(2)
struct A
{
unsigned char a;
unsigned short b;
};
struct B
{
unsigned char c;
unsigned int d;
};
/*恢复C编译器内存的缺省字节对齐方式*/
#pragma pack()
struct C
{
unsigned char e;
A A_a;
B B_b;
unsigned short f;
};
void main()
{
C*C_c;
unsigned char i []={ 23,3,4,5,6,7,8,56,68,
37,98,100,67,89,86,97,12,34,
37,98,100,67,89,86,97,12,34};
printf("数组i的十六进制显示:\n"
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\n",
i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7],i[8],
i[9],i[10],i[11],i[12],i[13],i[14],i[15],i[16],i[17],
i[18],i[19],i[20],i[21],i[22],i[23],i[24],i[25],i[26]);
C_c = (C*)i;
printf( "结构体C_c中变量e的值: e = 0x%04x\n"
"结构体C_c中结构体A_a中的值: a = 0x%04x b = 0x%04x\n"
"结构体C_c中结构体B_b中的值: c = 0x%04x d = 0x%04x\n"
"结构体C_c中变量f的值: f = 0x%04x\n\n",
C_c->e,
C_c->A_a.a,C_c->A_a.b,
C_c->B_b.c,C_c->B_b.d,
C_c->f);
printf( "结构体C_c中结构体e 地址:&e = 0x%04x\n"
"结构体C_c中结构体A_a 地址:&A_a = 0x%04x\n"
"结构体C_c中变量b 地址:&b = 0x%04x\n"
"结构体C_c中结构体B_b 地址:&B_b = 0x%04x\n"
"结构体C_c中变量d 地址:&d = 0x%04x\n"
"结构体C_c中变量f 地址:&f = 0x%04x\n",
&(C_c->e),
&(C_c->A_a), &(C_c->A_a.b),
&(C_c->B_b), &(C_c->B_b.d),
&(C_c->f));
system("pause");
}
例程分析:所有的字节对齐书均按照上面给出的说明计算
1)若#pragm pack(2) 和#pragm pack()语句注释掉,则为默认的n=4字节对齐。
结构体A_a的strAlignsize_A = min(#pragma pack(4),sizeof(b)) = 2
结构体B_b的strAlignsize_B = min(#pragma pack(4),sizeof(d)) = 4.
A.结构体C_c中的变量e字节对齐数为1,e=0x17,其地址为0x18fcd0;
B.结构体A_a作为结构体C_c的成员,其对齐字节数为2,所以需要向e变量的
后一个地址补空,使结构体A_a的对齐地址为0x18fcd2.这样结构体A_a的
起始地址相对于结构体C_c的起始地址偏移量0x18fcd2-0x18fcd0=2为2字
节的倍数。
C.考虑结构体A_a中,变量a的字节对齐数为1,a的起始地址为结构体A_a初
始偏移量为0,但对于结构体C_c的偏移量为2,&a = 0x18fcd2.故其取值
为a = 0x04;变量b的字节对齐数为2,要达到字节对齐,需要向变量a后
补一个字节的空。此时&b = 0x18fcd4,相对于结构体A_a的偏移量为
0x18fcd4 - 0x18fcd2 = 2为2字节的倍数,故 b = 0x0706(小端模式);
结构体A_a的对齐字节数为2,而整个结构体所占用的空间4个字节恰好为
strAlignsize_A = 2的整数倍,不用补空。
D.结构体B_b作为结构体C_c的成员,其对齐字节数为4,结构体A_a的变量b
的下一个地址为0x18fcd6,相对于结构体C_c的起始地址偏移量
0x18fcd6-0x18fcd0=6不是2字节的倍数,所以需要向b变量的后两个地址
(0x18fcd6和0x18fcd7)补空,使结构体B_b的对齐地址为0x18fcd8.这样结
构体B_b的起始地址相对于结构体C_c的起始地址偏移量
0x18fcd8-0x18fcd0=8为4字节的倍数.
E.考虑结构体B_b中,变量c的字节对齐数为c,c的起始地址为结构体B_b初
始偏移量为0,但对于结构体C_c的偏移量为8,&c = 0x18fcd8.故其取值
为c = 0x44;变量d的字节对齐数为4,要达到字节对齐,需要向变量c后