我們先看一道
ibm和微軟的筆試題:
ibm筆試題:
structa;
structb;
sizeof( a)=6, sizeof(b)=8,
為什麼?
注:sizeof(short)=2,sizeof(long)=4
微軟筆試題:
struct example1
;struct example2
;int main(int argc, char* argv)
輸出結果?
要能清除的分析上面的問題就要搞清楚結構體變數的成員在記憶體裡是如何分布的、成員先後順序是怎樣的、成員之間是連續的還是分散的、還是其他的什麼形式?其實這些問題既和軟體相關又和硬體相關。所謂軟體相關主要是指和具體的程式語言的編譯器的特性相關,編譯器為了優化
cpu訪問記憶體的效率,在生成結構體成員的起始位址時遵循著某種特定的規則,這就是所謂的
結構體成員「對齊」;
所謂硬體相關主要是指
cpu的「位元組序」問題,也就是大於乙個位元組型別的資料如
int型別、
short
big-endian
和little-endian
little-endian
就是低位位元組排放在記憶體的低位址端,高位位元組排放在記憶體的高位址端;
big-endian
就是高位位元組排放在記憶體的低位址端,低位位元組排放在記憶體的高位址端。
intel
、vax
和unisys
處理器的計算機中的資料的位元組順序是
little-endian
,ibm
大型機和大多數unix
平台的計算機中位元組順序是
big –endian。關與
big-endian
和little-endian
問題本文暫不做詳細討論,本文將以小端機(此處為
intel x86
架構的計算機)、os:
windowsxp
和vc++6.0
編譯器來詳細討論結構體成員的「對齊」問題。
前面說了
,為了優化
cpu訪問記憶體的效率,程式語言的編譯器在做變數的儲存分配時就進行了分配優化處理,優化規則大致原則是這樣
: 對於
n位元組的元素
(n=2,4,8,...)
,它的首位址能被
n整除,這種原則稱為「對齊
」,如word(2位元組)
的值應該能被
2整除的位置,
dword(4
位元組)應該在能被
4整除的位置。
對於結構體來說,結構體的成員在記憶體中順序存放,所佔記憶體位址依次增高,第乙個成員處於低位址處,最後乙個成員處於最高位址處,但結構體成員的記憶體分配不一定是連續的,編譯器會對其成員變數依據前面介紹的
「對齊」原則進行處理。對待每個成員類似於對待單個
n位元組的元素一樣,依次為每個元素找乙個適合的首位址,使得其符合上述的「對齊」原則。通常編譯器中可以設定乙個對齊引數
n,但這個
n並不是結構體成員實際的對齊引數,
vc++6.0
中結構體的每個成員實際對齊引數
n通常是這樣計算得到的n=
min(sizeof(
該成員型別),
n)(n為
vc++6.0
中可設定的值)。
成員的記憶體分配規律是這樣的:從結構體的首位址開始向後依次為每個成員尋找第乙個滿足條件的首位址
x
,該條件是
x
%
n
=
0
,
並且整個結構的長度必須為各個成員所使用的對齊引數中最大的那個值的最小整數倍
,
不夠就補空位元組
。結構體中所有成員的對齊引數
n的最大值稱為結構體的對齊引數
。vc++6.0中n
預設是8
個位元組,可以修改這個設定的對齊引數,方法為在選單「工程」的「設定」中的「
c/c++
」選項卡的「分類」中
「code generation
」的「struct member alignment
」中設定,
1byte
、2byte
、4byte
、8byte
、16byte
等幾種,預設為
8byte
結構體成員的記憶體對齊
include void printf arr quint8 data,int len,quint8 base num if 16 base num printf n struct frame big struct frame small struct frame union union int m...
關於結構體的成員對齊與結構體整體對齊
大多數計算機體系結構中,對記憶體操作時按整字訪問才能達到最高效率,相當於是以空間換取時間,看似浪費了記憶體空間,但換來了訪問效率,先來說說三個概念 系統對齊值,自身對齊值,有效對齊值,三個概念的單位均為位元組,一開始概念不懂沒關係,可以對照後面的程式和記憶體分布圖來理解 1,系統對齊值 對於不同的作...
結構體與記憶體對齊
三結構體 1.結構體是一種自定義型別 原生型別 自定義型別 2.結構體使用時先定義結構體型別再定義變數 或者同時定義 struct student struct student s1 struct student s1 typedef struct student s1 s1 s 3.結構體從陣列進...