關于偉創 偉創新聞 偉創案例 網站套餐 聯系方式
只做吸引客戶的精品站!

C++中的內存對齊

洛陽軟件開發師 / 2013/3/2 8:10:20
[核心提示] 因為CPU每次都是從以2字節(16位CPU)或是4字節(32位CPU)的整數倍的內存地址中讀進數據的。
C++中的內存對齊

關于內存對齊

一:

1.什么是內存對齊

假設我們同時聲明兩個變量:

char a;

short b;

用&(取地址符號)觀察變量a,

b的地址的話,我們會發現(以16位CPU為例):

如果a的地址是0x0000,那么b的地址將會是0x0002或者是0x0004。

那么就出現這樣一個問題:0x0001這個地址沒有被使用,那它干什么去了?答案就是它確實沒被使用。因為CPU每次都是從以2字節(16位CPU)或是4字節(32位CPU)的整數倍的內存地址中讀進數據的。如果變量b的地址是0x0001的話,那么CPU就需要先從0x0000中讀取一個short,取它的高8位放入b的低8位,然后再從0x0002中讀取下一個short,取它的低8位放入b的高8位中,這樣的話,為了獲得b的值,CPU需要進行了兩次讀操作。

 

但是如果b的地址為0x0002,

那么CPU只需一次讀操作就可以獲得b的值了。所以編譯器為了優化代碼,往往會根據變量的大小,將其指定到合適的位置,即稱為內存對齊(對變量b做內存對齊,a、b之間的內存被浪費,a并未多占內存)。

2.結構體內存對齊規則

結構體所占用的內存與其成員在結構體中的聲明順序有關,其成員的內存對齊規則如下:

(1)每個成員分別按自己的對齊字節數和PPB(指定的對齊字節數,32位機默認為4)兩個字節數最小的那個對齊,這樣可以最小化長度。

(2)復雜類型(如結構)的默認對齊方式是它最長的成員的對齊方式,這樣在成員是復雜類型時,可以最小化長度。

(3)結構體對齊后的長度必須是成員中最大的對齊參數(PPB)的整數倍,這樣在處理數組時可以保證每一項都邊界對齊。

(4)計算結構體的內存大小時,應該列出每個成員的偏移地址,則其長度=最后一個成員的偏移地址+最后一個成員數的長度+最后一個成員的調整參數(考慮PPB)。

下面舉例說明上述規則:

#include

#pragma pack(2) //指定PPB為2

struct T{

char a; //偏移地址0

int b; //偏移地址2

char c; //偏移地址6

};

#pragma pack() //恢復原來默認PPB,32位下為4

int main(int argc,char * argv[])

{

printf("sizeof(struct T));

return 0;

}

最后輸出的結果為:8。語句#pragma pack(2)的作用是指定結構體按2字節對齊,即PPB=2。分析如下:

變量a默認為1字節,PB=2,所以a按1字節對齊,a的偏移地址為0。

變量b默認為4字節(在32位機器中int為4字節),PB=2,所以b按2字節對齊,b的偏移地址為2。

變量c默認為1字節,PB=2,所以c按1字節對齊,偏移地址為6。

此時結構體的計算出的字節數為7個字節。最后按規則3,結構體對齊后的字節數為8。sizeof(T)=6+1+1=8

3.范例

(1)#pragma pack(2) //指定PPB為2

struct T{

char a; //偏移地址0

char b; //偏移地址1

int c; //偏移地址2

};

則sizeof(T)=最后一個成員的偏移地址+最后一個成員數的長度=2+4=6。

(2)struct T1{

char a; //偏移地址0

char b; //偏移地址1

int c; //偏移地址4

};

struct T2{

char a; //偏移地址0

int b; //偏移地址4

char c; //偏移地址8

};

PPB=4,則sizeof(T1)=4+4=8;sizeof(T2)=8+1=9,9不能整除4,故調整數為3,即sizeof(T2)=8+1+3=12

4.注意的問題

(1)字節對齊取決于編譯器;

(2)一定要注意PPB大小,PPB大小由pragam pack(n)指定;

(3)結構體占用的字節數要能被PPB整除。

二:

(1)sizeof也可以對一個函數調用求值,其結果是函數返回類型的大小,函數并不會被調用。

(2)終于搞懂struct結構體內存分配問題了,結構體中各個成員字節對齊遵循以下幾個原則:

1.結構體每個成員相對于結構體首地址的偏移量(offset)都是(這個)成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節(internal

adding);

例如有以下一個結構體

struct

ex {

int i;

char t;

int n;

}

第1個成員偏移量為0,是int型成員大小4(假設這太機器的整型長度占4個字節)的整數倍。

第2個成員

t

為char型,他的大小為1,首先假設在成員i和t之間沒有填充字節,由于i是整型,占4個字節那么在沒有填充之前,第2個成員t相對于結構體的偏移量為4,他是t成員大小1的4倍,符合此條件,所以系統在給結構體第2個成員分配內存時,不會在i和t之間填充字節以到達對齊的目的。

當分配結構體第3個成員n時,首先發現是一個整型數據,大小為4,沒有填充之前,n相對于結構體首地址偏移量為:前面2個成員+填充字節=5,所以當系統發現5不是4(成員大小)的整數倍時,會在成員t之后(或者說n之前)填充3個字節,以使n的偏移量到達8而成為4的整數倍。這樣這個結構體占用內存情況暫時為4+1+3+4。

2.結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之后加上填充字節(trailing

padding)。

上面的結構體內存分配以后還要看是否滿足此條件,假設在最末一個成員之后不需填充字節數,那么這個結構體的大小為12。而ex結構體中最寬基本類型成員為int,大小為4,12為4的整數倍,所以無須再在最末一個成員之后加上填充字節了。所以sizeof(ex)=12;

如果一個結構體如下所示struct

ex1{

int i;

char t;

int n;

char add;

}

那么sizeof(ex1)

=16;原因就是在最后一個成員之后填充了3個字節。

3.還有一個額外的條件:結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;

4.對于結構體成員屬性中包含結構體變量的復合型結構體再確定最寬基本類型成員時,應當包括復合類型成員的子成員。但在確定復合類型成員的偏移位置時則是將復合類型作為整體看待。

5總結出一個公式:結構體的大小等于最后一個成員的偏移量加上其大小再加上末尾的填充字節數目,即:

sizeof( struct ) = offsetof( last item ) + sizeof( last item ) +

sizeof( trailing padding )

尊重作者原創 除非特別聲明,偉創科技所有均為偉創原創報道,轉載請注明原文鏈接。
原文地址:http://www.tgpeyz.live/SoftWare/View.asp?id=358  所屬類別:軟件開發
相關內容
洛陽軟件開發需要多少錢? 2019/12/6
10種不同類型的軟件開發 2019/11/5
如何更好的完成軟件開發的項目 2018/9/18
偉創技術-婷婷:身為.NET程序員的斷想 2017/2/18
【洛陽網絡公司技術分享】身為.NET程序員的斷想 2016/1/28
猜你喜歡
站長換位思考 用戶需要怎樣的網站設計 2015/7/9
你的網站已經遇到了哪些瓶頸 2012/11/10
總結2013年4月偉創科技簽約網站制作項目客戶 2013/5/9
各行各業都要防范客戶被員工帶走,網絡公司也不例外 2014/8/18
新手如何才能做好網頁 2018/1/20
網絡營銷的職能 2012/9/26
偉創科技即日起正常上班,需要建站的客戶朋友請來電咨詢。 2013/2/16
人人都能用的10條網站易用性技巧 2013/12/19
企業網站設計有什么風格?分別是哪些? 2015/9/21
你應當拒絕無根據的修改需求 2012/11/26
偉創熱點
關于我們
公司簡介
我們的優勢
企業文化
公司愿景
加入偉創
偉創官方博客
金牌項目
網站建設
網站優化
軟件開發
整合設計
網站運營
網站套餐
基礎型網站
展示型網站
商務型網站
購物、商店型網站
FLASH動畫型網站
行業、門戶型網站
幫助中心
客戶中心
公司SEO培訓
seo顧問服務
支付方式
聯系我們
我們的位置
關注我們
新浪微博
騰訊微博
人人小站
QQ空間推薦
花瓣網
建站百科全書
Copyright 2007-2012 LYWHY.Inc Sitemap 豫ICP備12012069號-1
Links
洛陽百科
建站百科
大乐透几点开奖