メモリは使用中に単一の順序で配置されるのではなく、迅速なアクセスを容易にするために特定の確立された規則に従って配置されます。
メモリの配置には 3 つの原則があります。
- データメンバのアライメント:メンバ自身のサイズに応じて、メンバ自身のサイズの整数倍のメモリアドレスからメンバが格納されます(位置0に格納された最初の要素を基準として)
- 構造体メンバの配置: 構造体メンバが含まれる場合、構造体メンバの格納場所は内部メンバの最大値の整数倍のアドレスから開始されます。
- 構造体の合計サイズの調整: 最大の内部メンバーの整数倍である必要があり、不足分は補われる必要があります。
構造体のメンバは宣言順に格納され、最初のメンバのアドレスは構造体全体のアドレスと同じになります。
特に指定のない限り、構造体の最大サイズのメンバに従ってアライメントされます(ダブルメンバがある場合は、8 バイトに従ってアライメントされます)。
C++11 以降、2 つのキーワード alignas と alignof が導入されました。このうち、alignof は型のアライメントを計算でき、alignas は構造体のアライメントを指定できますが、
alignas が自然なアライメントの最小単位より小さい場合は無視されます。
offsetof
構造体のメンバー変数のオフセットを表示したり、構造体のメモリ アラインメントを学習したりすると便利です。
#include<iostream>
#include<stddef.h>
#include<bits/stdc++.h>
using namespace std;
struct alignas(4) Info2{
uint8_t a;
uint32_t b;
uint16_t c;
//uint16_t d;
}mys;
int main(){
cout<<sizeof(Info2)<<endl;
Info2 temp;
int offset_a = offsetof(Info2, a);
int offset_b = offsetof(Info2, b);
int offset_c = offsetof(Info2, c);
//int offset_d = offsetof(Info2, d);
cout << "Offset of a: " << offset_a << endl;
cout << "Offset of b: " << offset_b << endl;
cout << "Offset of c: " << offset_c << endl;
//cout << "Offset of d: " << offset_d << endl;
return 0;
}