1.結構體的第一個元素地址必須是0x…..0(是受內存對齊這個影響產生的結果)
2.結構體成員地址是通過對齊規則和自身大小共同影響的,規則如下:
如果設定對齊方式爲n個字節對齊,而某結構體成員大小爲m,那麼該結構體成員的地址必須爲min(n,m)的整數倍,比如double在64位平臺是8字節,指定對齊方式爲1個字節對齊,則地址隨意,若爲2個字節對齊,則地址只能是0 2 4 8
3.通過以上方式,即可算出結構體所有成員(附帶填充所佔字節)的大小q,而結構體的大小必須爲大於q的min(n,maximum)的最小整數倍(n語義同上,maxiumum爲最大的成員字節數)
下面我們來通過實例來搞懂上面的規則
#include <iostream>
using std::cout;
using std::endl;
#pragma pack(1)
struct Test {
char c; // 1 byte
double d; // 8 byte
int i; // 4 byte
short s; // 2 byte
float f; // 4 byte
};
#pragma pack()
#pragma pack(2)
struct Test2 {
char c; // 1 byte
double d; // 8 byte
int i; // 4 byte
short s; // 2 byte
float f; // 4 byte
};
#pragma pack()
#pragma pack(8)
struct Test8 {
char c; // 1 byte
double d; // 8 byte
int i; // 4 byte
short s; // 2 byte
float f; // 4 byte
};
#pragma pack()
int main() {
//Test結構體以1字節對齊,總大小爲1的倍數 因此爲所有成員大小之和即可無需填充
Test test;
printf("Test 以%ld byte 對齊\n",alignof(Test));
printf("Test結構體大小: %ld\n",sizeof(Test));
printf("Test.c address: %p\n",&test.c);
printf("Test.d address: %p\n",&test.d);
printf("Test.i address: %p\n",&test.i);
printf("Test.s address: %p\n",&test.s);
printf("Test.f address: %p\n",&test.f);
//Test結構體以2字節對齊,總大小必須爲2的倍數,成員與成員填充之和爲(可以通過地址相減加尾元素大小) 20爲2的倍數無需填充
Test2 test2;
printf("Test2 以%ld byte 對齊\n",alignof(Test2));
printf("Test2結構體大小: %ld\n",sizeof(Test2));
printf("Test2.c address: %p\n",&test2.c);
printf("Test2.d address: %p\n",&test2.d);
printf("Test2.i address: %p\n",&test2.i);
printf("Test2.s address: %p\n",&test2.s);
printf("Test2.f address: %p\n",&test2.f);
//Test結構體以8字節對齊,總大小必須爲8的倍數,成員與成員填充之和爲 27不爲8的倍數,繼續填充直到32
Test8 test8;
printf("Test8 以%ld byte 對齊\n",alignof(Test8));
printf("Test8結構體大小: %ld\n",sizeof(Test8));
printf("Test8.c address: %p\n",&test8.c);
printf("Test8.d address: %p\n",&test8.d);
printf("Test8.i address: %p\n",&test8.i);
printf("Test8.s address: %p\n",&test8.s);
printf("Test8.f address: %p\n",&test8.f);
return 0;
}