c 記憶體對齊原則

2021-08-27 05:23:44 字數 3121 閱讀 1536

struct/class/union記憶體對齊原則有四個:

1).資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如說是陣列,結構體等)的整數倍開始(比如int在32位機為4位元組, 則要從4的整數倍位址開始儲存),基本型別不包括struct/class/uinon。

2).結構體作為成員:如果乙個結構裡有某些結構體成員,則結構體成員要從其內部"最寬基本型別成員"的整數倍位址開始儲存.(struct a裡存有struct b,b裡有char,int ,double等元素,那b應該從8的整數倍開始儲存.)。

3).收尾工作:結構體的總大小,也就是sizeof的結果,.必須是其內部最大成員的"最寬基本型別成員"的整數倍.不足的要補齊.(基本型別不包括struct/class/uinon)。

4).sizeof(union),以結構裡面size最大元素為union的size,因為在某一時刻,union只有乙個成員真正儲存於該位址。

原則:1.結構體內成員按自身按自身長度自對齊。 自身長度,如char=1,short=2,int=4,double=8,。所謂自對齊,指的是該成員的起始位置的記憶體位址必須是它自身長度的整數倍。如int只能以0,4,8這類的位址開始

2.結構體的總大小為結構體的有效對齊值的整數倍

結構體的有效對齊值的確定:

1)當未明確指定時,以結構體中最長的成員的長度為其有效值

2)當用#pragma pack(n)指定時,以n和結構體中最長的成員的長度中較小者為其值。

3)當用__attribute__ ((__packed__))指定長度時,強制按照此值為結構體的有效對齊值

如果pragma pack和__attribute__同時指定則以__attribute__ 的為準。

需要說明的是,不管pragma pack和__attribute__如何指定,結構體內部成員的自對齊仍然按照其自身的對齊值。

structa

;structb

例項解釋:下面以class為代表no.1

class data; 

cout << sizeof(data) << endl;

no.2

class data; 

cout << sizeof(data) << endl;

顯然程式no.1 輸出的結果為 8    no.2 輸出的結果為 16 .

no.1最大的資料成員是4bytes,1+4=5,補齊為4的倍數,也就是8。而no.2為8bytes,1+8=9,補齊為8的倍數,也就是16。

no.3

class data; 

cout << sizeof(data) << endl;

no.4

class data; 

cout << sizeof(data) << endl;

no.3執行結果為 12  no.4執行結果為 8

class中的資料成員放入記憶體的時候,記憶體拿出乙個記憶體塊來,資料成員們排隊乙個乙個往裡放,遇到太大的,不是把自己劈成兩半,能放多少放多少,而是等下乙個記憶體塊過來。這樣的話,就可以理解為什麼no.3,no.4兩端的**輸出結果不一樣了,因為左邊是1+(3)+4+1+(3)=12,而右邊是1+1+(2)+4=8。括號中為補齊的bytes。

no.5

class bigdata; 

class data;

cout << sizeof(bigdata) << " " << sizeof(data) << endl;

no.6

class bigdata; 

class data;

cout << sizeof(bigdata) << " " << sizeof(data) << endl;

no.5和no.6執行結果均為: 48

在預設條件下,記憶體對齊是以class中最大的那個基本型別為基準的,如果class中有自定義型別,則遞迴的取其中最大的基本型別來參與比較。在no.5和no.6中記憶體塊乙個接乙個的過來接走資料成員,一直到第5塊的時候,bigdata裡只剩1個char了,將它放入記憶體塊中,記憶體塊還剩7個bytes,接下來是個int(4bytes),能夠放下,所以也進入第5個記憶體塊,這時候記憶體塊還剩3bytes,而接下來是個double(8bytes),放不下,所以要等下乙個記憶體快到來。因此,no.5的data的size=33+4+(3)+8=48,同理no.6應該是33+(7)+8=48。

順便提一下union: 共用體表示幾個變數共用乙個記憶體位置,在不同的時間儲存不同的資料型別和不同長度的變數。在union中,所有的共用體成員共用乙個空間,並且同一時間只能儲存其中乙個成員變數的值。

記憶體對齊的主要作用是:

2、  效能原因:經過記憶體對齊後,cpu的記憶體訪問速度大大提公升。具體原因稍後解釋。

圖一:這是普通程式設計師心目中的記憶體印象,由乙個個的位元組組成,而cpu並不是這麼看待的。

圖二:cpu把記憶體當成是一塊一塊的,塊的大小可以是2,4,8,16位元組大小,因此cpu在讀取記憶體時是一塊一塊進行讀取的。塊大小成為memory access granularity(粒度) 本人把它翻譯為「記憶體讀取粒度」 。

假設cpu要讀取乙個int型4位元組大小的資料到暫存器中,分兩種情況討論:

1、資料從0位元組開始

2、資料從1位元組開始

再次假設記憶體讀取粒度為4。

圖三:當該資料是從0位元組開始時,很cpu只需讀取記憶體一次即可把這4位元組的資料完全讀取到暫存器中。

當該資料是從1位元組開始時,問題變的有些複雜,此時該int型資料不是位於記憶體讀取邊界上,這就是一類記憶體未對齊的資料。

圖四:此時cpu先訪問一次記憶體,讀取0—3位元組的資料進暫存器,並再次讀取4—5位元組的資料進暫存器,接著把0位元組和6,7,8位元組的資料剔除,最後合併1,2,3,4位元組的資料進暫存器。對乙個記憶體未對齊的資料進行了這麼多額外的操作,大大降低了cpu效能。

這還屬於樂觀情況了,上文提到記憶體對齊的作用之一為平台的移植原因,因為以上操作只有有部分cpu肯幹,其他一部分cpu遇到未對齊邊界就直接罷工了。

C 記憶體對齊原則

c 記憶體對齊原則 1 在沒有 pragam pack巨集的情況下,struct class union記憶體對齊原則有四個 資料成員對齊規則 結構 struct 或聯合 union 的資料成員,第乙個資料成員放在offset為0的位置,以後每個資料成員儲存的起始位置都是放在該資料成員大小的整數倍位...

記憶體對齊原則

一 記憶體對齊的原因 1 平台移植原因 不是所有的硬體平台都能任意訪問任意位址上的資料,有些硬體平台只能在某些特定位址處讀取特定的資料,否則會丟擲硬體異常 2 效能原因 資料結構 尤其是棧 應盡可能的在自然邊界對齊。原因在於,訪問未對齊的記憶體,處理器需要進行兩次訪問,而訪問對齊的記憶體,處理器只需...

記憶體對齊原則

首先由乙個程式引入話題 1 環境 vc6 windows sp22 程式13 include 45 using namespace std 6 7struct st1 8 13 14struct st2 15 20 21int main 22 27 程式的輸出結果為 sizeof st1 is 12...