王若
摘要:內(nèi)存地址對齊,是一種在計算機內(nèi)存中排列數(shù)據(jù)、訪問數(shù)據(jù)的一種方式。當(dāng)今的計算機在計算機內(nèi)存中讀寫數(shù)據(jù)時都是按字(word)大小塊來進行操作的?;绢愋蛿?shù)據(jù)對齊就是數(shù)據(jù)在內(nèi)存中的偏移地址必須等于一個字(word)的倍數(shù),按這種存儲數(shù)據(jù)的方式,可以提升系統(tǒng)在讀取數(shù)據(jù)時的性能。有時候為了對齊數(shù)據(jù),可能必須在上一個數(shù)據(jù)結(jié)束和下一個數(shù)據(jù)開始的地方插入一些沒有用處字節(jié),這就是結(jié)構(gòu)體數(shù)據(jù)對齊。
關(guān)鍵詞:結(jié)構(gòu);數(shù)據(jù)
一、假設(shè)計算機的字大小為4個字節(jié),因此變量在內(nèi)存中的首地址都是滿足4地址對齊,CPU只能對4的倍數(shù)的地址進行讀取,而每次能讀取4個字節(jié)大小的數(shù)據(jù)
假設(shè)有一個整型的數(shù)據(jù)a的首地址不是4的倍數(shù),因此想讀取a的數(shù)據(jù),CPU要進行兩次內(nèi)存讀取,而且還要對兩次讀取的數(shù)據(jù)進行處理才能得到a的數(shù)據(jù),而一個程序的瓶頸往往不是CPU的速度,而是取決于內(nèi)存的帶寬,因為CPU得處理速度要遠(yuǎn)大于從內(nèi)存中讀取數(shù)據(jù)的速度,因此減少對內(nèi)存空間的訪問是提高程序性能的關(guān)鍵[1]。從上例可以看出,采取內(nèi)存地址對齊策略是提高程序性能的關(guān)鍵。
二、結(jié)構(gòu)體默認(rèn)的規(guī)則
本文所述的環(huán)境均是在32位編譯器的編譯環(huán)境中,一般編譯器默認(rèn)對齊方式是4字節(jié)。
總結(jié)結(jié)構(gòu)體的數(shù)據(jù)對齊方式滿足條件:
1、結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除。2、結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址的偏移量(offset)都是成員自身大小的整數(shù)倍,如有需要編譯器會在成員之間加上填充字節(jié)。3、結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要編譯器會在最末一個成員之后加上填充字節(jié)。
三、手動對齊方式
如果編譯器自動實現(xiàn)結(jié)構(gòu)體對齊,我們就稱為自動對齊,與之相反,使用#pragma進行對齊的就是手動對齊。
#pragma備用告訴編譯器,程序員自己希望的對齊方式。比如,雖然編譯器的默認(rèn)對齊方式是4,但是如果我們不希望按照4對齊,而是希望是8,這個時候就必須使用#pragma進行手動對齊了。
常用的設(shè)置手動對齊的命令有兩種:第一種是#pragmapack(),這種就是設(shè)置編譯器1字節(jié)對齊,不過也可以認(rèn)為是設(shè)置為不對齊或者取消對齊;第二種是
#pragmapack(4),這個括號中的數(shù)字表示希望以多少字節(jié)進行對齊。
我們需要#prgamapack(n)開頭,以#pragmapack()結(jié)尾,定義一個區(qū)間,這個區(qū)間內(nèi)的對齊參數(shù)就是n。
舉例說明
(一)自動對齊方式或者是默認(rèn)4字節(jié)對齊
分析代碼:根據(jù)基本數(shù)據(jù)類型對齊規(guī)則可知,c(字節(jié)),i(4字節(jié)),d(8字節(jié)),b(2字節(jié))。是不是結(jié)果就是1+4+8+2呢?很明顯不是,c是首元素,不需要對齊,但是后面的就需要對齊了,i是4字節(jié),但是它的起始偏移量只有1字節(jié),不能整除4,因此就在c后面再加3個字節(jié),當(dāng)遇到d時,由于之前的偏移量就是8,所以不需要偏移,在b之前有16字節(jié),這時也不需要偏移就是直接加上2。所以最后結(jié)果就是1+3+4+8+2=20,對不對呢?其實是不對的,因為18不是默認(rèn)對齊4的整數(shù)倍,還需要在后面補充2字節(jié)。一共就是20字節(jié)。
分析:該結(jié)果就是24字節(jié),分析同上,但是在最后一步不一樣,對齊是8字節(jié),所以在b后面還需要添加6字節(jié)。最終結(jié)果就是24.
四、結(jié)語
需要字節(jié)對齊的根本原因在于CPU訪問數(shù)據(jù)的效率問題。因為計算機可以處理數(shù)據(jù)位數(shù)都是確定的,這時候就說明它一次性只能處理確定位數(shù)的數(shù)據(jù),但是當(dāng)認(rèn)為造成該數(shù)據(jù)不在計算機一次性可訪問的范圍內(nèi)的時候,計算機就會按照一定的優(yōu)化方法來處理,這樣是更加方便和快捷的處理數(shù)據(jù)。也就是強制的要求一來簡化了處理器與內(nèi)存之間傳輸系統(tǒng)的設(shè)計,二來可以提升讀取數(shù)據(jù)的速度。
參考文獻
[1] 陳榮,蔡志勇,胡保安. 基于嵌入式操作系統(tǒng)VxWorks數(shù)據(jù)采集系統(tǒng)軟件設(shè)計[J]. 科技廣場,2005,(06):82-84.