gcc資料結構對齊之 why

2022-09-06 20:36:10 字數 1493 閱讀 3291

gcc 支援 aligned 和 packed 屬性指定資料對齊,那麼在了解對齊規則之前,需要解決第乙個以為,我們為什麼需要資料對齊?請看下圖:

相信學過彙編的朋友都很熟悉這張圖,這張圖就是cpu與記憶體如何進行資料交換的模型,其中,左邊藍色的方框是cpu,右邊綠色的方框是記憶體,記憶體上面的0~3是記憶體位址。這裡我們這張圖是以32位cpu作為代表,我們都知道,32位cpu是以雙字(dword)為單位進行資料傳輸的,也正因為這點,造成了另外乙個問題,那麼這個問題是什麼呢?這個問題就是,既然32位cpu以雙字進行資料傳輸,那麼,如果我們的資料只有8位或16位資料的時候,是不是cpu就按照我們資料的位數來進行資料傳輸呢?其答案是否定的,如果這樣會使得cpu硬體變的更複雜,所以32位cpu傳輸資料無論是8位或16位都是以雙字進行資料傳輸。

好了,有了上面的基礎,就可以解釋為什麼需要記憶體對齊了。

1. 如果訪問大小為乙個位元組的資料(eg : char 型別),假設該資料放在記憶體位址1開始的位置,那麼這個資料占用的記憶體位址為1,那麼cpu通過乙個指令週期,讀出位址d0-d7 中的資料到暫存器中,然後通過移位指令移動相應的位元組即可訪問該資料。

2. 比如,乙個int型別4位元組的資料如果放在上圖記憶體位址1開始的位置,那麼這個資料占用的記憶體位址為1~4,那麼這個資料就被分為了2個部分,乙個部分在位址0~3中,另外一部分在位址4~7中,又由於32位cpu以雙字進行傳輸,所以,cpu會分2次進行讀取,一次先讀取位址0~3中內容,再一次讀取位址4~7中資料,最後cpu提取並組合出正確的int型別資料,捨棄掉無關資料。那麼反過來,如果我們把這個int型別4位元組的資料放在上圖從位址0開始的位置會怎樣呢?讀到這裡,也許你明白了,cpu只要進行一次讀取就可以得到這個int型別資料了。沒錯,就是這樣,這次cpu只用了乙個週期就得到了資料,由此可見,對記憶體資料的擺放是多麼重要啊,擺放正確位置可以減少cpu的使用資源。

由於上面解釋的原因,gcc為代表的各種編譯器預設採用了自然邊界對齊的方式,那麼什麼是自然對齊,什麼是對齊的記憶體位址呢, 請看下面的解釋:

a. 一般計算機的記憶體是以位元組(byte,等於8bit)為最小單元的。記憶體位址相當於從0開始的位元組偏移數。如果乙個記憶體位址是n的倍數,我們就說它是n位元組對齊的(n-byte aligned)。

b. 對於c/c++中的基本資料型別,假設它的長度為n位元組,那麼該型別的變數會被編譯器預設分配到n位元組對齊的記憶體上。例如,char的長度是1位元組,char型別變數的位址將是1位元組對齊的(任意值均可); int的長度是4位元組,所以int型別變數將被分配到4位元組對齊的位址上。這種預設情況下的變數對齊方式又稱作自然對齊(naturally aligned)。

需要說明的是,以上對齊都是gcc編譯器幫我們自動完成的,一般情況下,程式設計師不需要過多的關注上面的內容。但是,如果你是在做一些記憶體對映相關或者協議相關的工作的時候,你必須很清楚了解資料在記憶體中每乙個位元組的組織方式的時候,你就很有必要了解gcc編譯器的預設對齊規則了,我們先從aligned和packed兩個gcc屬性說起.

GCC結構對齊小結

1,在結構中各成員按其宣告順序在記憶體中順序儲存,第乙個成員的位址即結構的位址.2,在預設情況下,結構的資料成員按其自身寬度自然對齊,使得每個field的offset為該成員寬度的整數倍,不足則前面補齊.3,整個結構的寬度是最大對齊量的整數倍,不足則在後面補齊.4,更改gcc編譯器的預設位元組對齊方...

資料結構的對齊

linux的對齊策略是 2位元組資料型別的位址必須是2的倍數,而較大的資料型別 例如 int,int float,double,long long 的位址必須是4的倍數.windows的對齊策略更加嚴格,認可k位元組基本型別物件的位址都必須是k的倍數.結構體的對齊,除了每個結構體成員對齊以外,還要滿...

資料結構對齊原則

一種資料結構 c語言中聚合資料型別的一類 可以被宣告為變數 陣列 指標等,用以實現比較複雜的資料結構 是一系列元素的集合,這些元素被稱為結構體成員 結構體成員需要用結構體名訪問。struct as1 s1是結構體變數 一般情況下,宣告出現三個部分的兩個部分即可 標誌或者變數可省略 結構體可以包含其他...