關於結構體內存對齊的剖析

2021-09-30 21:08:20 字數 1722 閱讀 7393

關於結構體內存對齊的問題,最直觀的體現便是在計算結構體大小的問題上。

我們來看乙個例子:

#include#includeint main()

s; printf("%d\n", sizeof(s));

system("pause");

return 0;

}

那麼在沒有考慮到結構體內存對齊之前,我們的常規思路應該是直接計算每個型別的大小,即1+4+8=13。但是我們看輸出結果:

結果並不是13,而是16。為什麼?

那麼這就是為什麼要有結構體內存對齊的原因了,我們先通過畫圖來剖析一下上述題目的結構體內存對齊產生的原因與過程。

我們在記憶體訪問定址時不能從任意處開始,所以我們在圖里定義一些確定的訪問位置。

如圖,在無結構體內存對齊的情況下(也就是按1+4+8=13計算),cpu讀取a的時候可以直接從記憶體裡讀取。而b佔4個位元組所以緊挨著a往下放,那麼cpu第一次訪問記憶體時要先把b在前面的3個位元組讀取出來,然後第二次訪問時再把b的剩下的乙個位元組讀取出來。那麼cpu光把b變數讀取就要訪問記憶體兩次,如果再記憶體中充滿了巨大的變數資料,cpu就要頻繁的訪問記憶體,那麼讀取資料的效能就會大大下降,很大程度上耗費了時間。

那麼記憶體對齊出現的原因總結為如下兩點:

效能原因:資料結構(尤其是棧),應該盡可能地在自然邊界上對齊。原因在於,為了未訪問對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體僅需訪問一次。

總的來說:結構體內存對齊的出現就是為了拿空間來換取時間

第乙個成員在與結構體變數偏移量為0的位址處。如上述例子的變數a,就是從偏移量為0處開始儲存。

其他成員要對齊到某個數字(對齊數)的整數倍的位址處。劃重點:對齊是指,除了第乙個變數,剩下的任何變數放入時的起始偏移量能整除對齊數。若不對齊,則讓起始偏移量增加至最小能整除對齊數的數。

任何編譯器都沒有預設對齊數。

每乙個成員都有乙個對齊數(一般為該成員自身的型別大小)。

結構體大小為最大對齊數的整數倍。

如果有巢狀結構體的情況,巢狀結構體對齊到自己最大對齊數的整數倍處,結構體的整體大小就是所有所有最大對齊數(含巢狀進來的結構體的對齊數)的整數倍。

那麼清楚了規則之後我們再來看這個題目就很明朗了。

如圖:變數a佔乙個位元組,所以可以被cpu直接讀取寫入,b佔4個位元組,所以b從起始偏移量為4的地方開始儲存,這樣在cpu讀取b只需訪問記憶體一次。

通常在設計結構體的時候,我們既要滿足對齊,又要節省空間,所以我們要讓占用空間小的成員盡量集中在一起。

例如:

struct s1	;	

struct s2

;

在上面這段**裡,s1和s2型別的成員一模一樣,但是s1和s2所佔空間大小有了一定的區別。

關於結構體,記憶體對齊,sizeof

程式設計師寶典中,關於結構體對齊問題,看了一晚上帖子,包括記憶體,cpu等等的,現在總算有些理解 要弄清結構體對齊,首先要明白為什麼要對齊?1.先想想簡單的hello.c整個執行過程中外設,記憶體,cpu的工作過程 計算機的所有工作都是要經過記憶體的,包括網頁得讀取等等 我們平時說的32位機器是指指...

關於結構體內存對齊方式

結構體的對齊方式必須是程式設計師所了解的,關於記憶體對齊方式的優點和部分知識可以參閱http www.ibm.com developerworks library pa dalign 結構體占用的儲存空間 struct sizeof 概要 結構體所占用的空間只可能是 1,2,4,6,8.結構體的記憶...

關於結構體內存對齊總結

記憶體對齊計算可謂是筆試題的必考題,但是如何按照計算原則算出正確答案一開始也不是很容易的事,所以專門通過例子來複習下關於結構體內存對齊的計算問題。編譯環境為vs2015 對齊原則 原則1 資料成員對齊規則 結構 struct 或聯合 union 的資料成員,第乙個資料成員放在offset為0的地方,...