共用方式為


Alignment

C++ 的其中一項低階功能可指定記憶體中物件的精確對齊方式,以充份利用特定的硬體架構。 根據預設,編譯程式會將類別和結構成員對齊其大小值:bool以及 1 位元組界限、 short 2 位元組界限、intlong、 和 4 位元組界限,以及doublelong long、 和 floatlong double 8 位元組界限char上。

在大部分情況下,您永遠不需要關注對齊方式,因為預設對齊已經是最佳方式。 不過,在某些情況下,您可以指定數據結構的自定義對齊方式,以大幅改善效能或節省記憶體。 在 Visual Studio 2015 之前,您可以使用 Microsoft 特定的關鍵詞 __alignof ,並 __declspec(align) 指定大於預設值的對齊方式。 從 Visual Studio 2015 開始,您應該使用 C++11 標準關鍵詞 alignofalignas 最大程式碼可移植性。 新關鍵詞的行為方式與 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 個字節。

第二個宣告包含兩個填補項目:

  1. char _pad0[3] 表示在 int b 4 位元組界限上對齊成員。
  2. 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];

alignofalignas

規範 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
}

另請參閱

數據結構對齊