アラインメント (C11)
C の低レベルの機能の 1 つは、ハードウェア アーキテクチャを最大活用するために、メモリ内のオブジェクトの正確なアラインメントを指定できる機能です。
データがそのデータ サイズの倍数であるアドレスに格納されていると、CPU の読み取りと書き込みの効率が向上します。 たとえば、4 バイトの整数が 4 の倍数であるアドレスに格納されていると、より効率的にアクセスできます。 データがアラインされていないと、CPU ではデータにアクセスするためにより多くのアドレス計算処理を行います。
既定では、コンパイラによって、サイズに基づいてデータがアラインされます。つまり、char
は 1 バイト境界、short
は 2 バイト境界、int
、long
、float
は 4 バイト境界、double
は 8 バイト境界と続きます。
また、頻繁に使用されるデータをプロセッサのキャッシュ ラインのサイズにアラインすることで、キャッシュ パフォーマンスを改善できます。 たとえば、サイズが 32 バイト未満の構造体を定義するとします。 32 バイトのアラインメントを使用して、構造体のすべてのインスタンスが効率的にキャッシュされるようにすると良いでしょう。
通常は、アラインメントについて心配する必要はありません。 コンパイラでは通常、ターゲット プロセッサとデータのサイズに基づいて、自然な境界にデータをアラインします。 データは、32 ビット プロセッサでは最大で 4 バイト境界、64 ビット プロセッサでは最大で 8 バイト境界にアラインされます。 ただし、場合によっては、データ構造にカスタム アラインメントを指定することで、パフォーマンスの向上やメモリの節約を実現できます。
C11 キーワード _Alignof
を使用して、型または変数の適切なアラインメントを取得したり、 _Alignas
を使用して、変数またはユーザー定義型のカスタム アラインメントを指定したりします。
で定義されている支援マクロ alignof
と <stdalign.h>
alignas
は、それぞれ _Alignof
と _Alignas
に直接マップされます。 これらのマクロは、C++ で使用されるキーワードと一致します。 そのため、2 つの言語間でコードを共有する場合は、コードの移植性を確保するために、C のキーワードではなく、そのマクロを使用すると役立つことがあります。
alignas
と _Alignas
(C11)
alignas
または _Alignas
を使用して、変数またはユーザー定義型のカスタム アラインメントを指定します。 これらは、構造体、共用体、列挙型、または変数に適用できます。
alignas
の構文
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
解説
_Alignas
は、register
指定子で宣言された typedef、ビットフィールド、関数、関数パラメーター、オブジェクトの宣言では使用できません。
1、2、4、8、16 などの 2 の累乗であるアラインメントを指定します。 型のサイズよりも小さい値は使用しないでください。
struct
と union
型のアラインメントは、任意のメンバーの最大のアラインメントと同じになります。 各メンバーのアラインメント要件が満たされるように、 struct
の中に埋め込みバイトが追加されます。
宣言に複数の alignas
指定子が存在する場合 (たとえば、それぞれ異なる alignas
指定子のメンバーを持つ struct
)、その struct
のアラインメントは少なくとも最も大きな指定子の値になります。
alignas
の例
この例では、C++ に移植可能であるため、支援マクロ alignof
を使用します。 動作は _Alignof
を使用する場合と同じです。
// Compile with /std:c11
#include <stdio.h>
#include <stdalign.h>
typedef struct
{
int value; // aligns on a 4-byte boundary. There will be 28 bytes of padding between value and alignas
alignas(32) char alignedMemory[32]; // assuming a 32 byte friendly cache alignment
} cacheFriendly; // this struct will be 32-byte aligned because alignedMemory is 32-byte aligned and is the largest alignment specified in the struct
int main()
{
printf("sizeof(cacheFriendly): %d\n", sizeof(cacheFriendly)); // 4 bytes for int value + 32 bytes for alignedMemory[] + padding to ensure alignment
printf("alignof(cacheFriendly): %d\n", alignof(cacheFriendly)); // 32 because alignedMemory[] is aligned on a 32-byte boundary
/* output
sizeof(cacheFriendly): 64
alignof(cacheFriendly): 32
*/
}
alignof
と _Alignof
(C11)
_Alignof
とその別名 alignof
では、指定された型のアラインメントがバイト単位で返されます。 型 size_t
の値を返します。
alignof
の構文
alignof(type)
_Alignof(type)
alignof
の例
この例では、C++ に移植可能であるため、支援マクロ alignof
を使用します。 動作は _Alignof
を使用する場合と同じです。
// Compile with /std:c11
#include <stdalign.h>
#include <stdio.h>
int main()
{
size_t alignment = alignof(short);
printf("alignof(short) = %d\n", alignment); // 2
printf("alignof(int) = %d\n", alignof(int)); // 4
printf("alignof(long) = %d\n", alignof(long)); // 4
printf("alignof(float) = %d\n", alignof(float)); // 4
printf("alignof(double) = %d\n", alignof(double)); // 8
typedef struct
{
int a;
double b;
} test;
printf("alignof(test) = %d\n", alignof(test)); // 8 because that is the alignment of the largest element in the structure
/* output
alignof(short) = 2
alignof(int) = 4
alignof(long) = 4
alignof(float) = 4
alignof(double) = 8
alignof(test) = 8
*/
}
必要条件
/std:c11
を使ってコンパイルします。
Windows SDK バージョン 10.0.20348.0 (バージョン 2104) 以降。 最新の SDK のダウンロードするには、「Windows SDK」を参照してください。 C11 および C17 開発用 SDK をインストールして使用する手順については、「C11 と C17 のサポートを Visual Studio にインストールする」を参照してください。
関連項目
/std
(言語の標準バージョンの指定)
C++ alignof
と alignas
コンパイラによるデータ アラインメントの処理