結構體的大小計算
結構體中可以定義的數據類型:
1.基本類型
2.上面已經出現過的數據類型,比如說上面已經定義過的結構體
3.指向自己的指針
因為內存對齊的問題,各個數據類型放的位置不同就會導致結構體的大小不一樣,那么到底怎樣計算一個結構體的大小呢?
先介紹一個概念——偏移量,結構體中的偏移量就是結構體成員和結構體變量的地址之差,比如說第一個結構體成員的偏移量就是0,第二個結構成員的偏移量就是第一個結構體成員的大小,假如第一個成員的是int b
;那么第二個結構體成員變量的偏移量就是4。
計算結構體大小的規則:
- 每一個成員的偏移量都必須是該成員的倍數。
- 結構體的大小必須是該結構體字節數最大成員類型的倍數。(注意是類型而不是變量)
例如下面的結構體:
例一:
struct A
{
char a;
short b;
int c;
};
第一個成員的偏移量都是0;一般可以不看,a的大小為1,所以成員b的偏移量為1,b的大小為2,1不是2的倍數,所以應該將1+1,成為2的倍數,成員c的偏移量就為1+1+2,是成員c的倍數,現在就符合計算結構體大小的第一條:該成員的偏移量是該成員大小的倍數,還有第二條規則:結構體大小是結構體最大成員的倍數,結構體的大小就是各個成員之和,a;2,b:2,c:4加起來就是8,該結構最大成員為c大小為4,滿足第二個條件,所以該結構體的大小就是8。
代碼:
#include <stdio.h>
int main ()
{
struct A
{
char a;
short b;
int c;
};
printf ("%d",sizeof(A));
return 0;
}
例二:
struct Data
{
char a;
int b;
int64_t c; 該數據類型是有符號的占64位的整形數據類型
char d;
}
成員a的偏移量就不用看了,上面有說每一個結構體第一個成員的偏移量都為0;但他的大小是1,也就是成員b的偏移量,成員b的大小是4,1不是4的倍數,所以a的大小1應該加上3,就是4,成員3的偏移量是8,成員c的大小是8,成員c的偏移量是成員c大小的倍數,就不用增加大小,成員d的偏移量是16,成員d的大小是1,偏移量是成員大小的倍數,現在就符合計算結構體大小的第一條:改成員的偏移量是該成員大小的倍數,還有第二條規則:結構體大小是結構體最大成員的倍數,最大成員為c,大小是8,結構體的大小就是各個成員之和,a:4,b:4,c:8,d:1所有的加起來就是17,但是17不是8的倍數,所以應該將17+7就是24,所以該結構體的大小就是24。
代碼:
#include <stdio.h>
int main ()
{
struct Data
{
char a;
int b;
long long c;
char d;
};
printf ("%d\n",sizeof(Data));
return 0;
}
聯合體(Union)大小的計算
1.聯合體特性
- 聯合體所有成員變量共享內存,相對於聯合體首地址偏移量都為0
- 同一時間只能存儲1個被選擇的變量,對其他成員變量賦值會覆蓋原變量
2.聯合體大小計算規則
- 聯合體大小要至少能容納最大的成員變量
- 聯合體大小要是所有成員變量類型最大值的整數倍(注意是類型而不是變量)
例:
typedef union u
{
char a;
int b[5];
double c;
int d[3];
}U;
U大小至少要容納最大的b[5]=4*5=20字節,同時要是變量類型最大值得整數倍,即sizeof(double)=8的整數倍,所有sizeof(U)=24
結構體嵌入聯合體的大小計算
計算規則
聯合體按照最大成員所占字節且為最大數據類型所對應的字節的最小整數倍的原則進行計算,它所占的字節數與結構體中其他成員所占字節的總和應為結構體中最大數據類型所對應的字節的最小倍數。
例
typedef struct
{
union
{
char a[10];
int b[2];
double c;
}test;
char d[5];
int e;
double f;
}Test;
根據上述規則,則聯合體中,最大占10字節,但又要為8的最小倍數,因此聯合體占16字節,然后 16+5+4+8=33 字節,不是結構體中最大數據類型 double 所對應的字節數 8的最小倍數,根據規則故結構體的大小為:16(聯合體所占字節)+5+3(空字節)+4+4(空字節)+8=40 字節。
結構體/聯合體嵌套結構大小的計算
當結構體里面嵌套有結構體時,其規則為:
1、嵌套的結構體前一個成員的偏移量應當是嵌套結構體中最大成員類型大小的整數倍;
2、結構體成員的大小必須是所有成員大小的整數倍,這里所有成員計算的是包括嵌套結構體內所有成員在內,而不是將嵌套的結構體當做一個整體。
如下例:
#include <iostream>
using namespace std;
struct A
{
char a1;
short int a2;
double a3;
char d;
};
struct B
{
int b2;
A a;
short int b1;
};
int main()
{
cout << sizeof(B)<<endl;
//system("pause");
}
對於A來說,A的大小可以使用之前的方法計算為24。而對於B,由於A結構體中最大成員類型為double,其占字節為8,因而B中的第一個成員b2的偏移量應該是8的倍數,即為8,然后再加上結構體A的大小,為 8 + 24 = 32,再然后加上b1的大小為2,結果為8 + 24 + 2 = 34。根據上面的規則2,其總大小要是所有成員大小的整數倍,因而必須是8的倍數,因而最終結果為40。
當結構體里面嵌套有聯合體時
1、嵌套聯合體前一個成員的偏移量應當是嵌套聯合體中最大成員類型大小的整數倍;
2、結構體成員的大小必須是所有成員類型大小的整數倍,這里所有成員計算的是包括嵌聯合體內所有成員在內,而不是將嵌套的聯合體當做一個整體。
#include <iostream>
using namespace std;
union A
{
char a1;
short int a2;
double a3[2];
char d;
};
struct B
{
int b2;
A a;
short int b1;
};
int main()
{
cout << sizeof(B)<<endl;
//system("pause");
}
輸出為32。
參考資料:
[1] 關於結構體、聯合體大小的計算 https://blog.csdn.net/qq_29775205/article/details/86538154
[2] 結構體大小問題:sizeof 嵌套結構體求大小(結構體里有結構體) https://blog.csdn.net/qq_19323819/article/details/82965040?tdsourcetag=s_pctim_aiomsg
C++在線編譯器地址:https://c.runoob.com/compile/12