棧上分配空間時的地址數值從大向小變化。
當int i(一般的)被分配4字節空間,那麼變量所占內存空間的首地址——通常簡稱變量的地址,是最小的地址。假定32位的i分配為2000、2001、2002、2003地址,2000即為i的地址。很多書上畫示意圖的時候,把地址數值從小向大變化,以及將i的最高字節的地址作為首地址,是不是有點想當然。
例子:假定我們用int打包4個字符(位域處理),在big-endian機器上,在最低地址先存儲高字節數據。i由javz構成,則分別分配為2000(存放j)、2001(存放a)、2002、2003地址。小端(little-endian)時&i地址編號2000保存的是(z)。
big endian是指低地址存放最高有效字節(MSB),而little endian則是低地址存放最低有效字節(LSB)。
x86系列采用little endian方式
[cpp]
void headP(void){
char j='J',a='a',v='v'/*,a2='z'*/;//對齊
printf("%p %p %p \n",&j,&a,&v);
unsigned int i=0;
i+=(j<<24)+(a<<16)+(v<<8);
printf("%p \n",&i);
char a2='z';//填空
i+=a2;
printf("%p \n",&a2);
char* cp=(char*)(&i);
printf("%p \n",(void*)(&cp));
*(cp+3)='j';
printf("%c%c%c%c\n",*cp,*(cp+1),*(cp+2),*(cp+3));//指向最後字節
printf("%c%c%c%c\n",*(cp+4),*(cp+5),*(cp+6),*(cp+7));
}
void headP(void){
char j='J',a='a',v='v'/*,a2='z'*/;//對齊
printf("%p %p %p \n",&j,&a,&v);
unsigned int i=0;
i+=(j<<24)+(a<<16)+(v<<8);
printf("%p \n",&i);
char a2='z';//填空
i+=a2;
printf("%p \n",&a2);
char* cp=(char*)(&i);
printf("%p \n",(void*)(&cp));
*(cp+3)='j';
printf("%c%c%c%c\n",*cp,*(cp+1),*(cp+2),*(cp+3));//指向最後字節
printf("%c%c%c%c\n",*(cp+4),*(cp+5),*(cp+6),*(cp+7));
}
輸出:
0012ff83 0012ff82 0012ff81
0012ff7c
0012ff80
0012ff78
zvaj
zvaJ
內存對齊和分配順序
例如例程中,大體按照程序文本順序分配空間;對於char之外的數據類型,通常按字對齊。如果例程中修改為
[cpp] view plaincopyprint?char a2='z',c='c';//填空
char a2='z',c='c';//填空這時a2填空,但是c在i之前分配空間。
雖然可以測試,但是我不能夠確定在其他情況下是否正確。