資源描述:
《深入理解字節(jié)對(duì)齊方式》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在應(yīng)用文檔-天天文庫(kù)。
1、字節(jié)對(duì)齊方式一、快速理解1.什么是字節(jié)對(duì)齊?在C語(yǔ)言中,結(jié)構(gòu)是一種復(fù)合數(shù)據(jù)類型,其構(gòu)成元素既可以是基本數(shù)據(jù)類型(如int、long、float等)的變量,也可以是一些復(fù)合數(shù)據(jù)類型(如數(shù)組、結(jié)構(gòu)、聯(lián)合等)的數(shù)據(jù)單元。在結(jié)構(gòu)中,編譯器為結(jié)構(gòu)的每個(gè)成員按其自然邊界(alignment)分配空間。各個(gè)成員按照它們被聲明的順序在內(nèi)存中順序存儲(chǔ),第一個(gè)成員的地址和整個(gè)結(jié)構(gòu)的地址相同。為了使CPU能夠?qū)ψ兞窟M(jìn)行快速的訪問(wèn),變量的起始地址應(yīng)該具有某些特性,即所謂的”對(duì)齊”.比如4字節(jié)的int型,其起始地址應(yīng)該位于4字節(jié)的邊界上,即起始
2、地址能夠被4整除.2.字節(jié)對(duì)齊有什么作用?字節(jié)對(duì)齊的作用不僅是便于cpu快速訪問(wèn),同時(shí)合理的利用字節(jié)對(duì)齊可以有效地節(jié)省存儲(chǔ)空間。對(duì)于32位機(jī)來(lái)說(shuō),4字節(jié)對(duì)齊能夠使cpu訪問(wèn)速度提高,比如說(shuō)一個(gè)long類型的變量,如果跨越了4字節(jié)邊界存儲(chǔ),那么cpu要讀取兩次,這樣效率就低了。但是在32位機(jī)中使用1字節(jié)或者2字節(jié)對(duì)齊,反而會(huì)使變量訪問(wèn)速度降低。所以這要考慮處理器類型,另外還得考慮編譯器的類型。在vc中默認(rèn)是4字節(jié)對(duì)齊的,GNUgcc也是默認(rèn)4字節(jié)對(duì)齊。3.更改C編譯器的缺省字節(jié)對(duì)齊方式在缺省情況下,C編譯器為每一個(gè)變量或
3、是數(shù)據(jù)單元按其自然對(duì)界條件分配空間。一般地,可以通過(guò)下面的方法來(lái)改變?nèi)笔〉膶?duì)界條件:·使用偽指令#pragmapack(n),C編譯器將按照n個(gè)字節(jié)對(duì)齊。·使用偽指令#pragmapack(),取消自定義字節(jié)對(duì)齊方式。另外,還有如下的一種方式:·__attribute((aligned(n))),讓所作用的結(jié)構(gòu)成員對(duì)齊在n字節(jié)自然邊界上。如果結(jié)構(gòu)中有成員的長(zhǎng)度大于n,則按照最大成員的長(zhǎng)度來(lái)對(duì)齊?!_attribute__((packed)),取消結(jié)構(gòu)在編譯過(guò)程中的優(yōu)化對(duì)齊,按照實(shí)際占用字節(jié)數(shù)進(jìn)行對(duì)齊。4.舉例說(shuō)明例1
4、structtest{charx1;shortx2;floatx3;charx4;};由于編譯器默認(rèn)情況下會(huì)對(duì)這個(gè)struct作自然邊界(有人說(shuō)“自然對(duì)界”我覺(jué)得邊界更順口)對(duì)齊,結(jié)構(gòu)的第一個(gè)成員x1,其偏移地址為0,占據(jù)了第1個(gè)字節(jié)。第二個(gè)成員x2為short類型,其起始地址必須2字節(jié)對(duì)界,因此,編譯器在x2和x1之間填充了一個(gè)空字節(jié)。結(jié)構(gòu)的第三個(gè)成員x3和第四個(gè)成員x4恰好落在其自然邊界地址上,在它們前面不需要額外的填充字節(jié)。在test結(jié)構(gòu)中,成員x3要求4字節(jié)對(duì)界,是該結(jié)構(gòu)所有成員中要求的最大邊界單元,因而tes
5、t結(jié)構(gòu)的自然對(duì)界條件為4字節(jié),編譯器在成員x4后面填充了3個(gè)空字節(jié)。整個(gè)結(jié)構(gòu)所占據(jù)空間為12字節(jié)。例2#pragmapack(1)//讓編譯器對(duì)這個(gè)結(jié)構(gòu)作1字節(jié)對(duì)齊structtest{charx1;shortx2;floatx3;charx4;};#pragmapack()//取消1字節(jié)對(duì)齊,恢復(fù)為默認(rèn)4字節(jié)對(duì)齊這時(shí)候sizeof(structtest)的值為8。例3#defineGNUC_PACKED__attribute__((packed))structPACKEDtest{charx1;shortx2;flo
6、atx3;charx4;}GNUC_PACKED;這時(shí)候sizeof(structtest)的值仍為8。二、深入理解什么是字節(jié)對(duì)齊,為什么要對(duì)齊?TragicJun發(fā)表于2006-9-189:41:00現(xiàn)代計(jì)算機(jī)中內(nèi)存空間都是按照byte劃分的,從理論上講似乎對(duì)任何類型的變量的訪問(wèn)可以從任何地址開(kāi)始,但實(shí)際情況是在訪問(wèn)特定類型變量的時(shí)候經(jīng)常在特定的內(nèi)存地址訪問(wèn),這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個(gè)接一個(gè)的排放,這就是對(duì)齊。對(duì)齊的作用和原因:各個(gè)硬件平臺(tái)對(duì)存儲(chǔ)空間的處理上有很大的不同。一些平臺(tái)
7、對(duì)某些特定類型的數(shù)據(jù)只能從某些特定地址開(kāi)始存取。比如有些架構(gòu)的CPU在訪問(wèn)一個(gè)沒(méi)有進(jìn)行對(duì)齊的變量的時(shí)候會(huì)發(fā)生錯(cuò)誤,那么在這種架構(gòu)下編程必須保證字節(jié)對(duì)齊.其他平臺(tái)可能沒(méi)有這種情況,但是最常見(jiàn)的是如果不按照適合其平臺(tái)要求對(duì)數(shù)據(jù)存放進(jìn)行對(duì)齊,會(huì)在存取效率上帶來(lái)?yè)p失。比如有些平臺(tái)每次讀都是從偶地址開(kāi)始,如果一個(gè)int型(假設(shè)為32位系統(tǒng))如果存放在偶地址開(kāi)始的地方,那么一個(gè)讀周期就可以讀出這32bit,而如果存放在奇地址開(kāi)始的地方,就需要2個(gè)讀周期,并對(duì)兩次讀出的結(jié)果的高低字節(jié)進(jìn)行拼湊才能得到該32bit數(shù)據(jù)。顯然在讀取效率上
8、下降很多。二.字節(jié)對(duì)齊對(duì)程序的影響:先讓我們看幾個(gè)例子吧(32bit,x86環(huán)境,gcc編譯器):設(shè)結(jié)構(gòu)體如下定義:structA{inta;charb;shortc;};structB{charb;inta;shortc;};現(xiàn)在已知32位機(jī)器上各種數(shù)據(jù)類型的長(zhǎng)度如下:char:1(有符號(hào)無(wú)符號(hào)同)short:2(有符號(hào)無(wú)符號(hào)同