C 中位元組對齊以及位元組對齊的意義

2021-08-02 18:27:30 字數 1536 閱讀 5975

對下面的類:

class b 

};

類b

物件的大小,如果直接計算是18(

4+2+8+4

),但是

sizeof(b)

結果是24。

多出來的

6個位元組是怎麼回事呢?其實是記憶體對齊的原因。編譯器在預設的情況下,分配給各個成員變數的記憶體大小似乎是向佔最大空間的成員變數對齊的(這裡我不敢肯定,還沒看到權威的說法)。在

b類中編譯器首先為m_a

分配空間,編譯器一次為

m_a分配

8個位元組(與最大成員

m_c對齊),實際上

m_a只佔

4個位元組,還有

4個位元組多。接著編譯器為

m_b分配空間,經檢查,

m_b只佔

2位元組,剛好前面還有

4個位元組多,所以

m_b就放在前面多出的那

4個位元組空間中,現在已經為

m_a和

m_b分配了空間,但是

m_a加上

m_b也就只有

6位元組,還有

2個位元組多。如果下面分配的變數剛好是

2位元組的話,那就剛剛好裝滿

8個位元組,沒有浪費空間,可是下面m_c是個

double

型別的變數,要佔

8個位元組,顯然

2個位元組是裝不下的,因此編譯器再為

m_c分配了

8個位元組的空間。剛裝滿,接下來又為

m_d分配空間,根據之前的規則,編譯器分配給

m_d的空間也是

8位元組。這樣看來,編譯器總共為

b的物件分配了

8+8+8=24

位元組的空間。如下圖所示:

分配時,以最長位元組(double m_c的8

位元組)為最小分配單元。

sizeof(b)為8

位元組的整數倍。

可能你覺得編譯器這樣做是浪費記憶體空間,但實際上這樣做是很適合

cpu做一些指令操作的。

1、各個硬體平台對儲存空間的處理不盡相同,比如一些cpu訪問特定的變數必須從特定的位址進行讀取,所以在這種架構下就必須進行位元組對齊了,要不然讀取不到資料或者讀取到的資料是錯誤的。

2、會對cpu的訪問效率產生影響:比如有些平台cpu從記憶體中偶數字址開始讀取資料,如果資料起始位址正好為偶數,則1個讀取週期就可以讀出乙個int型別的值,而如果資料其實位址為奇數,那我們就需要2個讀取週期讀出資料,並對高位址和低位址進行拼湊,這在讀取效率上顯然已經落後了很多了。

一句話:用空間效率來換時間效率。

如果還是覺得空間比較重要,那麼可以通過設定編譯屬性或使用編譯器指令#pragma

來指定編譯器所做的對齊方式。

例如語句:

#pragma pack(1)

就是設定向

1位元組對齊。這時使用

sizeof(b)

得出的結果就是

18了。

位元組對齊的意義

一 為什麼需要進行位元組對齊 1 各個硬體平台對儲存空間的處理不盡相同,比如一些cpu訪問特定的變數必須從特定的位址進行讀取,所以在這種架構下就必須進行位元組對齊了,要不然讀取不到資料或者讀取到的資料是錯誤的。2 會對cpu的訪問效率產生影響 比如有些平台cpu從記憶體中偶數字址開始讀取資料,如果資...

mysql位元組對齊 C 位元組對齊彙總

一 什麼是位元組對齊 現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。二 位元組對齊的原因和...

c 位元組對齊

1.虛函式 如果 classa 有虛函式,編譯器會給每個 classa 物件新增乙個隱藏成員,該隱藏成員儲存了乙個指向虛函式表的指標.所以 sizeof classa 如果比你預想的多了 4 位,不要驚奇,因為多了乙個 size 指標 但是這個隱藏指標是先算還是後算呢?class a int a c...