C++中struct的空間計算

大寫的ZDQ發表於2019-04-03

一般使用sizeof判斷struct所佔的位元組數,那麼計算規則是什麼呢?

關鍵詞:

1.變數的起始地址和變數自身的位元組數
2.以最大變數位元組數進行位元組對齊(倍數關係)。

注:這裡介紹的原則都是在沒有#pragma pack巨集的情況下

先舉個例子:

struct A
{
    char a[5];
    int b;
    short int c;
}struct A;

在上例中,要計算 sizeof(a) 是多少?

有兩個原則:

1)各成員變數存放的起始地址相對於結構的起始地址的偏移量必須為該變數的型別所佔用的位元組數的倍數 即當 A中的a佔用了5個位元組後,b需要佔用四個位元組,此時如果b直接放在a後,則b的起始地址是5,不是sizeof(int)的整數倍,所以 需要在a後面補充3個空位元組,使得b的起始地址為8. 當放完b後,總空間為5+3+4 = 12. 接著放c,此時為 12 + 2 = 14.

2)為了確保結構的大小為結構的位元組邊界數(即該結構中佔用最大空間的型別所佔用的位元組數)的倍數, 所以在為最後一個成員變數申請空間後,還會根據需要自動填充空缺的位元組。 這是說A中佔用最大空間的型別,就是int型了,佔用了4個位元組,那麼規定A佔用的空間必須是4的整數倍。本來計算出來佔用的空間為14, 不是4的整數倍,因此需要在最後補充2個位元組。最終導致A佔用的空間為16個位元組。

再舉個例子:

struct B
{
    char *d;
    short int e;
    long long f;
    char c[1];
}b;
 
void test2() {
	printf("%d\n", sizeof(b));
}

對於此題,需要注意的一點是:windows系統對long long是按照8位元組進行對齊的,但是Linux系統對long long則是按照4位元組對齊的。

因此: d佔用4位元組(因為d是指標)

e佔用2位元組

f佔用8位元組,但是其起始地址為為6,不是4的整數倍(對於Linux系統),或不是8的整數倍(對於Windows系統),因此對e之後進行位元組補齊,在這裡不管對於Linux還是Windows都是補充2個位元組,因此 f 的起始地址是8,佔用8個位元組。

對於c,它佔用了1個位元組,起始地址是16,也是1的整數倍。

最後,在c之後需要對整個B結構體佔用的空間進行補齊,目前佔用空間是16+1 = 17個位元組。

對於Linux,按4位元組補齊(long long 是按4位元組補齊的),因此補充了3位空位元組,最後佔用空間是 17 + 3 = 20位元組。

對於Windows系統,是按8位元組補齊的,因此就補充了7個位元組,最後佔用的空間是24位元組。

相關文章