Alignment
C++ 的其中一項低階功能可指定記憶體中物件的精確對齊方式,以充份利用特定的硬體架構。 根據預設,編譯程式會將類別和結構成員對齊其大小值:bool
以及 1 位元組界限、 short
2 位元組界限、int
long
、 和 4 位元組界限,以及double
long long
、 和 float
long double
8 位元組界限char
上。
在大部分情況下,您永遠不需要關注對齊方式,因為預設對齊已經是最佳方式。 不過,在某些情況下,您可以指定數據結構的自定義對齊方式,以大幅改善效能或節省記憶體。 在 Visual Studio 2015 之前,您可以使用 Microsoft 特定的關鍵詞 __alignof
,並 __declspec(align)
指定大於預設值的對齊方式。 從 Visual Studio 2015 開始,您應該使用 C++11 標準關鍵詞 alignof
和 alignas
最大程式碼可移植性。 新關鍵詞的行為方式與 Microsoft 特定的擴充功能相同。 這些延伸模組的檔也適用於新的關鍵詞。 如需詳細資訊,請參閱alignof
運算符、alignas
規範和對齊。 C++ 標準不會針對比目標平臺的編譯程式預設值小的界限指定對齊方式的封裝行為,因此在此情況下,您仍然需要使用 Microsoft #pragma pack
。
使用 aligned_storage 類別,以使用自定義對齊方式配置數據結構。 aligned_union類別用於指定具有非trivial 建構函式或解構函式之等位的對齊方式。
對齊和記憶體位址
對齊是記憶體位址的屬性,以數字位址取 2 乘冪的模數來表示。 例如,0x0001103F模數 4 的位址是 3。 據說該位址與 4n+3 對齊,其中 4 表示所選的 2 權力。 位址的對齊方式取決於所選的 2 電源。 相同位址取 8 的模數為 7。 如果位址的對齊方式為 Xn+0,則稱為對齊 X。
CPU 會執行指令,以處理儲存在記憶體中的資料。 數據會以其記憶體中的位址來識別。 單一的日期也有大小。 如果我們的位址對齊其大小,我們稱之為自然對齊的日期。 否則稱為 不 對齊。 例如,如果用來識別它的位址具有8位元組的對齊方式,則8位元組浮點數會自然對齊。
數據對齊的編譯程序處理
編譯程式會嘗試以防止數據不對齊的方式進行數據配置。
針對簡單的資料類型,編譯器指派的位址會是以位元組為單位之資料類型大小的倍數。 例如,編譯程式會將位址指派給類型 long
為 4 倍數的變數,並將位址的底部 2 位設定為零。
編譯程式也會以自然對齊結構每個元素的方式填補結構。 請考慮下列程式代碼範例中的 結構 struct x_
:
struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} bar[3];
編譯器會填補這個結構,以便強制執行自然對齊。
下列程式代碼範例示範編譯程式如何將填補結構放在記憶體中:
// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
} bar[3];
這兩個宣告都會傳回 sizeof(struct x_)
12 個字節。
第二個宣告包含兩個填補項目:
char _pad0[3]
表示在int b
4 位元組界限上對齊成員。char _pad1[1]
表示在 4 位元組界限上對齊 結構的struct _x bar[3];
陣列元素。
填補會以允許自然存取的方式對齊 的 bar[3]
元素。
下列程式代碼範例顯示 bar[3]
陣列設定:
adr offset element
------ -------
0x0000 char a; // bar[0]
0x0001 char pad0[3];
0x0004 int b;
0x0008 short c;
0x000a char d;
0x000b char _pad1[1];
0x000c char a; // bar[1]
0x000d char _pad0[3];
0x0010 int b;
0x0014 short c;
0x0016 char d;
0x0017 char _pad1[1];
0x0018 char a; // bar[2]
0x0019 char _pad0[3];
0x001c int b;
0x0020 short c;
0x0022 char d;
0x0023 char _pad1[1];
alignof
和 alignas
規範 alignas
是可攜式的 C++ 標準方式,可指定變數和使用者定義型別的自定義對齊方式。 運算子 alignof
同樣是一種標準、可攜式的方式,可取得指定型別或變數的對齊方式。
範例
您可以在 alignas
類別、結構或等位或個別成員上使用。 遇到多個 alignas
規範時,編譯程式會選擇具有最大值的規範。
// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
alignas(4) char arr[3];
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應