簡介
現代計算機一般是32比特或64比特地址對齊,如果要訪問的變數沒有對齊,可能會觸發匯流排錯誤。
當數據小於計算機的字(word)尺寸,可能把幾個數據元素放在一個字中,稱為包入(packing)。
定義
記憶體地址a被稱為n位元組對齊,當a是n的倍數(n應是2的冪)。
一次記憶體訪問被稱為對齊的,當被訪問的數據長度為n位元組且該數據地址為n位元組對齊。如果記憶體未對齊,稱作misaligned。顯然,位元組訪問總是對齊的。
記憶體指針是對齊的,如果它所指的數據是對齊的。指向聚合數據(aggregate data,如struct或數組)是對齊的,若且唯若它的每個組成數據是對齊的。
x86體系結構
x86體系架構最初是不要求記憶體對齊。一些
SSE2指令要求數據是128比特(16位元組)對齊。有些CPU指令用於未對齊訪問如MOVDQU。讀寫記憶體操作僅在對齊時才是原子的。
C語言struct在x86上的對齊
C語言數據結構內的成員先後順序不能改變。
常見的C語言編譯器在32比特x86上,double是8位元組對齊,但Linux上是4位元組對齊(編譯選項-malign-double實現8位元組對齊)。
#pragma pack(push) /* push current alignment to stack */#pragma pack(1) /* set alignment to 1 byte boundary */struct MyPackedData{ char Data1; long Data2; char Data3;};#pragma pack(pop) /* restore original alignment from stack */
這個結構在32位系統的大小為6位元組。
預設packing與#pragma pack
Microsoft編譯器的項目預設packing(編譯選項/Zp)與#pragma pack指令。#pragma pack指令僅能減少packing尺寸。
數組步長
數組步長(stride of an array,也稱increment, pitch或step size)是
程式設計時,相鄰數組元素在記憶體中的開始地址的距離,度量單位可以是位元組或者數組元素個數。步長不可小於數組元素的尺寸,但可以大於,表示有填充的位元組。
數組步長如果等於數組元素的尺寸,則數組在記憶體中是連續的。這可稱為
單位步長(unit stride)。非單位步長適用於
二維數組或
多維數組。
類型雙關