爲什麼要字節對齊:
爲了更快的讀取數據;不是本文重點,不想多解釋;
對齊規則:
1、確定對齊單位
1、環境默認對齊單位
WIN默認8字節對齊
Linux 32位 默認4字節對齊,64位默認8字節對齊
2、結構體最大數據類型長度
1、含有數組:數組就是多個基本類型變量,比如 char a[10],就是有a[0] 到 a[9] 共10個char類型變量;
2、含有結構體:比較嵌套的結構體中最大與本結構體中最大,取大的那個;
3、預編譯指令#pragma pack(n)手動設置 n取1 2 4 8 16
上面三者取最小的,就是實際對齊單位;
2、結構體(struct)的數據成員,第一個數據成員放的位置offset在0的地方,以後每個數據成員的offset爲該數據成員大小的整數倍的地方(比如int在32位機爲4字節,則要從4的整數倍地址開始存儲)
3、結構體作爲成員的對齊規則。
如果一個結構體B裏嵌套另一個結構體A,則結構體A應從offset爲A內部最大成員的整數倍的地方開始存儲。(struct B裏存有struct A,A裏有char,int,double等成員,那A應該從8的整數倍開始存儲。),結構體A中的成員的對齊規則仍滿足2、3。
注意:
1. 結構體A所佔的大小爲該結構體成員內部最大元素的整數倍,不足補齊。
2. 不是直接將結構體A的成員直接移動到結構體B中
4、結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍,不足的要補齊。
練習
1、按照規則1;結構體b的對齊單位是多少?
#pragma pack(8)
struct A
{
int a;
double b;
float c;
};
struct
{
char e[10];
int f;
short h;
struct A i;
}B;
結果爲8;
2、驗證規則3中結構體A應從offset爲A內部最大成員的整數倍的地方開始存儲;計算結構體b的大小
#pragma pack(8)
struct A
{
short a;
int b;
};
struct
{
char e[2];
int f;
short g;
struct A j;
double i;
}B;
main() {
printf("short%d\n", sizeof(short));//2
printf("int%d\n", sizeof(int));//4
printf("double%d\n", sizeof(double));//8
printf("B%d",sizeof( B));//32
}
結果爲32而不是24說明其存放方式是
e | e | * | * | f | f | f | f |
g | g | * | * | a | a | * | * |
b | b | b | b | * | * | * | * |
i | i | i | i | i | i | i | i |
而不是
e | e | * | * | f | f | f | f |
g | g | a | a | b | b | b | b |
i | i | i | i | i | i | i | i |
2、驗證規則3中1. 結構體A所佔的大小爲該結構體成員內部最大元素的整數倍,不足補齊。;計算結構體b的大小
#pragma pack(8)
struct A
{
short a;
int b;
short c;
};
struct
{
char e[2];
int f;
short g;
struct A j;
short k;
double i;
}B;
main() {
printf("B%d",sizeof( B));//40
}
結果是40而不是32;說明存放是
e | e | * | * | f | f | f | f |
g | g | * | * | a | a | * | * |
b | b | b | b | c | c | * | * |
k | k | * | * | * | * | * | * |
i | i | i | i | i | i | i |
i |
而不是
e | e | * | * | f | f | f | f |
g | g | * | * | a | a | * | * |
b | b | b | b | c | c | k | k |
i | i | i | i | i | i | i | i |