對齊 (C++)
Microsoft 專有的
使用__declspec(align(#))來精確地控制使用者定義的資料 (例如,靜態配置或函式中的自動資料) 的對齊方式。
如需有關對齊方式的詳細資訊,請參閱IPF,x 86 和 x64 上的 Windows 資料對齊。
__declspec( align( # ) ) declarator
備註
撰寫應用程式,請使用最新的處理器指令介紹一些新的條件約束和問題。 特別是,許多新的指令要求資料必須對齊 16 位元組的界限。 此外,調整快取行的大小的特定處理器常用的資料,藉以改善快取效能。 比方說,如果您定義的結構,其大小是小於 32 個位元組,可能會想要對齊它為 32 個位元組,以確保該結構類型的物件會有效地快取。
# 為對齊值。 有效的項目都是整數乘冪數從 1 到 8192 (位元組)、 2、 4、 8、 16、 32 或 64 例如 2。 declarator是您所宣告所對齊的資料。
請參閱 __alignof 如需如何傳回型別的值size_t也就是型別對齊需求。 與 __unaligned 如需如何以 64 位元的處理器為目標時,宣告未對齊的指標。
您可以使用__declspec(align(#))定義時struct, union,或class,或當您宣告變數。
沒有__declspec(align(#)),Visual C++ 對齊自然界限的資料,例如的 4 位元組的整數,在 4 個位元組的界限和 8 位元組邊界上的八位元組雙精度浮點數大小為基礎的資料。 類別或結構中的資料對齊的類別或結構在其自然對齊] 和 [目前的 [packing] 設定的最小值 (# pragma 從pack或**/Zp**編譯器選項)。
您無法指定函式參數的對齊方式。
例如:
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
這個型別現在有 32 個位元組對齊的屬性,這表示所有執行個體必須在 32 位元界限上開始。 使用這個成員的型別宣告的其他結構型別保留這種類型的對齊屬性,也就是任何結構與Str1如項目會有至少 32 的對齊方式屬性。
摘要如下:
除非覆寫的__declspec(align(#)),純量的結構成員的對齊方式的最小的大小和目前的封裝。
除非覆寫的__declspec(align(#)),結構的對齊方式是個別的對齊方式,其成員的最大值。
結構成員會放在從其父結構,也就是其對齊方式,晚於或等於前一個成員的結尾位移最小的倍數開始的位移。
結構的大小是最大對齊最小的倍數大於或等於它的最後一位成員的結尾位移。
請注意, sizeof(struct Str1)等於 32,如此,如果建立 Str1 物件的陣列,陣列的基底是 32 個位元組對齊,則陣列的每個成員也會 32 位元組對齊。 若要建立的陣列,其基底正確對齊,請使用 _aligned_malloc,或撰寫您自己的配置器。 請注意該標準 allocators,例如 malloc,C++ 運算子 new,和 Win32 allocators 傳回將最有可能不完全密切的記憶體 **__**declspec(align(#))結構的陣列。
sizeof任何結構的值是最後的成員,加上該成員的大小、 進位到最接近的最大的成員對齊值,或是整個結構的對齊值的倍數的位移,以更高。
__declspec(align(#))可能只會增加對齊方式的限制。
如需詳細資訊,請參閱:
對齊範例
定義新型別與 __declspec(align(#))
對齊執行緒區域儲存區內的資料
如何對齊適用於資料的封裝
結構對齊範例 (x64 專用)
對齊範例
下列範例所示如何__declspec(align(#))會影響資料結構的對齊方式和調整。 範例假設定義如下:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
在下列範例中, S1結構定義使用__declspec(align(32))。 所有使用S1、 是否為變數的定義或其他型別宣告,確保此結構資料為 32 位元組對齊。 sizeof(struct S1)傳回 32,和S1有 16 存放四個整數所需的 16 位元組的填補位元組。 每個int成員需要 4 個位元組對齊,但是結構本身的對齊方式宣告為 32,讓整體的對齊方式為 32。
struct CACHE_ALIGN S1 { // cache align all instances of S1
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned
在下列範例中, sizeof(struct S2)會傳回 16,這是完全成員大小的總和,因為發生此情形是檔案對齊之最大對齊需求 (8 的倍數)。
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
在下列範例中, sizeof(struct S3)傳回 64。
struct S3 {
struct S1 s1; // S3 inherits cache alignment requirement
// from S1 declaration
int a; // a is now cache aligned because of s1
// 28 bytes of trailing padding
};
在下列範例中,請注意, a有自然型別的,如此一來,4 個位元組對齊。 不過, S1必須 32 位元組對齊。 20 八個位元組的與邊框距離,請依照下列a,讓s1美元起位移 32。 S4然後會繼承的對齊需求S1,因為它是最大對齊需求,在結構中的。 sizeof(struct S4)傳回 64。
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
下列三個變數宣告也使用__declspec(align(#))。 在每個案例中,變數必須是 32 位元組對齊。 如果是陣列,陣列,而不是每個陣列成員的基底地址會是 32 位元組對齊。 sizeof值將不會影響每個陣列成員__declspec(align(#))。
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
若要對齊陣列中的每個成員,如下所示的程式碼應:
typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];
在下列範例中,請注意對齊結構本身和對齊的第一個元素都是完全相同:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
S6與S7有相同的對齊方式、 配置和大小的特性。
在下列範例中,解決的開始對齊方式的 a、 b、 c、 d 4、 1、 4 和 1,分別是和。
void fn() {
int a;
char b;
long c;
char d[10]
}
如果記憶體配置在堆積上的對齊方式,取決於哪一個配置函式被呼叫。 例如,如果您使用malloc,結果會視運算元大小而定。 如果 arg > = 8、 對齊方式將會是 8 位元組對齊。 If arg < 第 8 對齊將會是第一次方 2 小於 arg。 比方說,如果您使用 malloc(7) 時,對齊方式是 4 個位元組。
定義新型別與 __declspec(align(#))
您可以定義一個型別包含對齊特性。
例如,您可以定義struct 都使用的對齊值,如下所示:
struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;
現在, aType和bType是相同的大小 (8 個位元組),但型別的變數bType將 32 位元組對齊。
對齊執行緒區域儲存區內的資料
靜態執行緒區域儲存區 (TLS) 以建立__declspec(thread)屬性,然後將映像服務項目對齊方式,如同一般的靜態資料中的 [TLS] 區段中。 作業系統會建立 TLS 資料配置資料 TLS 區段的大小,及應注重 TLS 區段對齊屬性。
下列範例會示範幾個要對齊的資料放入執行緒區域儲存區。
// put an aligned integer in TLS
__declspec(thread) __declspec(align(32)) int a;
// define an aligned structure and put a variable of the struct type
// into TLS
__declspec(thread) __declspec(align(32)) struct F1 { int a; int b; } a;
// create an aligned structure
struct CACHE_ALIGN S9 {
int a;
int b;
};
// put a variable of the structure type into TLS
__declspec(thread) struct S9 a;
如何對齊適用於資料的封裝
/Zp編譯器選項和pack pragma 影響封裝資料結構和等位的成員。 這個範例會示範如何**/Zp**和__declspec(align(#))一起運作:
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
下表列出每個成員在各種不同的位移**/Zp** (或 # pragma pack) 的值,顯示兩者的互動方式。
變數 |
/ Zp1 |
/ Zp2 |
/ Zp4 |
/ Zp8 |
---|---|---|---|---|
a |
0 |
0 |
0 |
0 |
b |
1 |
2 |
2 |
2 |
c |
3 |
4 |
4 |
8 |
d |
32 |
32 |
32 |
32 |
e |
40 |
40 |
40 |
40 |
f |
41 |
42 |
44 |
48 |
將 sizeof (S) |
64 |
64 |
64 |
64 |
如需詳細資訊,請參閱 /Zp (結構成員對齊)。
因此,物件的位移為基礎的位移上一個物件和目前的 packing 設定,除非該物件有__declspec(align(#))屬性,在此情況下的對齊方式根據前一個物件的位移和__declspec(align(#)) 物件的值。