這篇文章主要講解了“C++內(nèi)存對(duì)齊怎么理解”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“C++內(nèi)存對(duì)齊怎么理解”吧!
成都創(chuàng)新互聯(lián)公司致力于成都網(wǎng)站制作、網(wǎng)站建設(shè),成都網(wǎng)站設(shè)計(jì),集團(tuán)網(wǎng)站建設(shè)等服務(wù)標(biāo)準(zhǔn)化,推過(guò)標(biāo)準(zhǔn)化降低中小企業(yè)的建站的成本,并持續(xù)提升建站的定制化服務(wù)水平進(jìn)行質(zhì)量交付,讓企業(yè)網(wǎng)站從市場(chǎng)競(jìng)爭(zhēng)中脫穎而出。 選擇成都創(chuàng)新互聯(lián)公司,就選擇了安全、穩(wěn)定、美觀的網(wǎng)站建設(shè)服務(wù)!
一、為什么要內(nèi)存對(duì)齊?
訪問(wèn)未對(duì)齊的內(nèi)存,處理器要訪問(wèn)兩次(數(shù)據(jù)先讀高位,再度地位),訪問(wèn)對(duì)齊的內(nèi)存,處理器只要訪問(wèn)一次,為了提高處理器讀取數(shù)據(jù)的效率,我們使用內(nèi)存對(duì)齊。Windows 默認(rèn)對(duì)齊數(shù)為8字節(jié),Linux 默認(rèn)對(duì)齊數(shù)為4字節(jié)。
使用內(nèi)存對(duì)齊的原因還有平臺(tái)的原因:不是所有的硬件平臺(tái)都能訪問(wèn)特定的地址上的任意數(shù)據(jù),某些平臺(tái)只能訪問(wèn)特定的地址上的獲取數(shù)據(jù),否則會(huì)拋出異常。
二、內(nèi)存對(duì)齊原則:
在內(nèi)存中,編譯器按照成員列表分別為 每個(gè)結(jié)構(gòu)體變量分配內(nèi)存,當(dāng)存儲(chǔ)過(guò)程中需要對(duì)齊的需求時(shí),編譯器會(huì)在成員之間留下額外的內(nèi)存空間。如果想要確認(rèn)結(jié)構(gòu)體占多少存儲(chǔ)空間,則使用關(guān)鍵字sizeof查看大小,如果想得知結(jié)構(gòu)體的某個(gè)特定成員在結(jié)構(gòu)體的位置,則使用offsetof(頭文件stddef.h)
結(jié)構(gòu)體或聯(lián)合體的數(shù)據(jù)成員、第一個(gè)成員放到0片便宜的地方,以后每個(gè)數(shù)據(jù)成員放到自身對(duì)齊的整數(shù)倍偏移處。(對(duì)齊數(shù)是變量自身大小和默認(rèn)對(duì)齊數(shù)的較小值)結(jié)構(gòu)體的大小必須是最大對(duì)齊數(shù)的整數(shù)倍。
三、對(duì)于結(jié)構(gòu)體字節(jié)對(duì)齊,有哪些規(guī)則?
總體上我們假設(shè)結(jié)構(gòu)體起始位置為0x0000,N為設(shè)置的n字節(jié)對(duì)齊,則滿(mǎn)足公式0x0000%N==0,來(lái)決定結(jié)構(gòu)體成員存儲(chǔ)的位置。
1.如果是采用默認(rèn)對(duì)齊規(guī)則,需要執(zhí)行以下的步驟:
(1)結(jié)構(gòu)體的成員的自身對(duì)值N(數(shù)據(jù)類(lèi)型占有的空間,比如在32位機(jī)器下int型為4字節(jié),自身對(duì)值為4)需要與存儲(chǔ)位置做出判斷。若滿(mǎn)足“起始位置%N=0”(除了結(jié)構(gòu)體的第一個(gè)成員,N也要必須滿(mǎn)足>=成員自身對(duì)齊值),則把該成員存放在該起始位置。若前一個(gè)成員與目前成員的存儲(chǔ)位置有一定的距離,則把該距離作為填充空間。
(2)所有結(jié)構(gòu)體的成員都分配完存儲(chǔ)位置之后,則還要結(jié)構(gòu)體本身也要進(jìn)行對(duì)齊。結(jié)構(gòu)體本身也要滿(mǎn)足“(M+X)%S=0”來(lái)進(jìn)行對(duì)齊,其中M+X是整個(gè)結(jié)構(gòu)體占有的存儲(chǔ)空間大小,M是所有結(jié)構(gòu)體的成員的存儲(chǔ)空間大小總和,X是為了滿(mǎn)足S的整數(shù)倍的填補(bǔ)空間大小,S是就是結(jié)構(gòu)體成員中自身對(duì)齊值最大的那個(gè)。
四、如果是采用#pragma pack(N)規(guī)則,需要執(zhí)行以下的步驟:
(1)結(jié)構(gòu)體成員的自身對(duì)齊值是偏移的量。若滿(mǎn)足“起始位置%N=0”(這里N是指定對(duì)齊值,即#pragma pack(N)),則可以把該成員存儲(chǔ)到該起始位置中,偏移量為該成員的自身對(duì)齊值(比如int型自身對(duì)齊值為4,占用4個(gè)字節(jié)的內(nèi)存位置)。
(2)結(jié)構(gòu)體自身對(duì)齊值為該結(jié)構(gòu)體的所有成員自身對(duì)齊值中最大的值,但又因?yàn)榻Y(jié)構(gòu)體的有效對(duì)齊值(即指定對(duì)齊值)為N,所以“(M+X)%N=0”,M+X是該結(jié)構(gòu)體存儲(chǔ)的空間大小。
五、為什么我的編譯器在結(jié)構(gòu)中留下了空洞?這導(dǎo)致空間浪費(fèi)而且無(wú)法與外部數(shù)據(jù)文件進(jìn)行“二進(jìn)制”讀寫(xiě)。能否關(guān)掉填充,或者控制結(jié)構(gòu)域的對(duì)齊方式?
當(dāng)內(nèi)存中的值合理對(duì)齊時(shí),很多機(jī)器都能非常高效地訪問(wèn)。例如,在按字節(jié)尋址的機(jī)器中,2字節(jié)的short int型變量必須放在偶地址上,而4字節(jié)的long int型變量則必須存放在4的整數(shù)倍地址上。某些機(jī)器甚至根本就不能訪問(wèn)沒(méi)有對(duì)齊的地址,因此必須要求所有的數(shù)據(jù)都正確地對(duì)齊。
六、什么叫做位域?
位域是指信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié), 而只需占幾個(gè)或一個(gè)二進(jìn)制位。例如在存放一個(gè)開(kāi)關(guān)量時(shí),只有0和1 兩種狀態(tài), 用一位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C語(yǔ)言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱(chēng)為“位域”或“位段”。所謂“位域”是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾 個(gè)不同的區(qū)域, 并說(shuō)明每個(gè)區(qū)域的位數(shù)。每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。 這樣就可以把幾個(gè)不同的對(duì)象用一個(gè)字節(jié)的二進(jìn)制位域來(lái)表示。
感謝各位的閱讀,以上就是“C++內(nèi)存對(duì)齊怎么理解”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)C++內(nèi)存對(duì)齊怎么理解這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!