内存字节对齐

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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后

相关文档
最新文档