結構是乙個或多個變數的集合,這些變數可能為不同的型別,為了處理的方便而將這些變數組織在乙個名字之下;
下面先來看乙個定義結構體的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include
#include
struct
testtype;
int
main()
在該結構體中定義了乙個char型別的變數first,乙個int型別的變數second和乙個double型別的變數third;在vs2013下進行編譯執行得到如下結果
按照我的理解char變數佔乙個位元組,那麼int的位址就是mytest+1。但從執行結果來看,int的位址卻是成了mytest+4。此時我就想到「記憶體對齊",記憶體對齊指的是:
那麼為什麼上面程式的執行結果會是這個樣子?先簡單介紹一下記憶體對齊的原因:
平台原因:不是所有的硬體平台都能訪問任意位址上的任意的資料,某些平台只能在某些地方讀取某些資料,否則會丟擲硬體異常。
效能原因:資料結構(尤其是棧)應該盡可能的在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要做兩次記憶體訪問;而對齊的記憶體訪問只需要一次(經過記憶體對齊後,cpu訪問記憶體的速度會大大提高)。
對原因2進行解釋:
cpu把記憶體看成是一塊一塊的,以2(short),4(int),8(double)為單位進行讀取的。簡單舉乙個例子:
假設cpu要讀取乙個4位元組大小的資料到暫存器中,分兩種情況討論:
資料從0位元組開始;
資料從1位元組開始;
兩種情況如圖所示:
當cpu從0位元組開始讀取的時候,只需要讀取一次即可把4位元組的內容讀取到暫存器中;當cpu從1位元組開始讀取的時候,顯然問題開始變得複雜,因為此時資料不再記憶體讀取邊界上,這是一類記憶體未對齊的資料。
此時記憶體先訪問一次記憶體,讀取0-3位元組資料到暫存器,並且再次讀取4-7位元組資料到暫存器中,接著把0位元組和6,7,8位元組的內容刪掉,然後合併1,2,3,4,位元組的內容3暫存器,顯然相比第一種情況而言,cpu進行了很多額外的操作,大大降低了cpu的效能。
結構體對齊規則
1.
第乙個成員在結構體變數偏移量為
0的位址處;
2.
其他成員變數要對齊到某個數字(對齊數)的整數倍的位址處;
//
對齊數=
編譯器預設的乙個對齊數與該成員的較小值;
vs
中預設的值為8;
linux
中的預設值為4;
3
.結構體總大小為最大對齊數(每個變數除了第乙個成員都有乙個對齊數,不包含預設對齊數的 整數倍;
4.
如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體 大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
下面開始分析本文開頭時的**:
在結構體testtype中最大資料成員的長度是8位元組,以8位元組為對齊係數,first佔1位元組,後面會有7位元組的空間,編譯器會填充3位元組,second佔4位元組,所以second會填充到first後面,third佔8位元組,因此mytest的大小是4+4+8=16位元組。
分析上面結構體資料成員的位址,根據位址我們顯然可以得出此結果完全符合上面的分析。
調整文章開頭結構體裡面的變數順序;
1
2
3
4
5
6
struct
testtype
;
並將該程式在vs2013下執行,輸出結果:
1
2
3
4
mytest位址是:bcfac8
char
變數位址是:bcfac8
double
變數位址是:bcfad0
int
變數位址是:24
分析上面**:
在結構體testtype中最大資料成員的長度是8位元組,以8位元組為對齊係數,first佔1位元組,後面會有7位元組的空間,double佔8位元組,編譯器會填充char後面的7位元組空間,int佔4位元組,編譯器會將其填充到8位元組,所以mytest的大小是3*8=24位元組。
分析上面結構體資料成員的位址,根據位址我們顯然可以得出此結果完全符合上面的分析。
結構體內存對齊
結構體內存對齊 一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這...
結構體內存對齊
一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的...
結構體內存對齊
對齊規則 每個特定平台上的編譯器都有自己的預設 對齊係數 也叫對齊模數 程式設計師可以通過預編譯命令 pragma pack n n 1,2,4,8,16來改變這一係數,其中的n就是你要指定的 對齊係數 規則 1 資料成員對齊規則 結構 struct 的資料成員,第乙個資料成員放在offset為0的...