sizeof()计算结构体的大小
原文鏈接:sizeof()計算結(jié)構(gòu)體的大小_海月汐辰-CSDN博客_結(jié)構(gòu)體的sizeof怎么計算
簡要說明:結(jié)構(gòu)體成員按照定義時的順序依次存儲在連續(xù)的內(nèi)存空間,但是結(jié)構(gòu)體的大小并不是簡單的把所有成員大小相加,而是遵循一定的規(guī)則,需要考慮到系統(tǒng)在存儲結(jié)構(gòu)體變量時的地址對齊問題。
一、沒有成員的結(jié)構(gòu)體占用的空間是多少個字節(jié)?
? ? ?答案是:1個字節(jié)。
? ? ?這就是實例化的原因(空類同樣可以被實例化),每個實例在內(nèi)存中都有一個獨一無二的地址,為了達到這個目的,編譯器往往會給一個空類或空結(jié)構(gòu)體(C++中結(jié)構(gòu)體也可看為類)隱含的加一個字節(jié),這樣空類或空結(jié)構(gòu)體在實例化后在內(nèi)存得到了獨一無二的地址,所以空類所占的內(nèi)存大小是1個字節(jié)。
二、首先介紹一個相關(guān)的概念——偏移量
? ? ? ? ? struct stru?
? ? ? ? ?{ ?
? ? ? ? ? ? ? ? ? ? int a; ?//start address is 0
? ? ? ? ? ? ? ? ? ?char b; ?//start address is 4
? ? ? ? ? ? ? ? ? ?int c; ?//start address is 8
? ? ? ? ?};
? ? ? ? ?偏移量指的是結(jié)構(gòu)體變量中成員的地址和結(jié)構(gòu)體變量地址的差。結(jié)構(gòu)體大小等于最后一個成員的偏移量加上最后一個成員的大小。顯然,結(jié)構(gòu)體變量中第一個成員的地址就是結(jié)構(gòu)體變量的首地址。比如上面的結(jié)構(gòu)體,第一個成員a的偏移量為0。第二個成員b的偏移量是第一個成員的偏移量加上第一個成員的大小(0+4),其值為4;第三個成員c的偏移量是第二個成員的偏移量應該是加上第二個成員的大小(4+1)。
三、在實際中,存儲變量時地址要求對齊,編譯器在編譯程序時會遵循兩條原則:
? ? ? ? ? ? ?(1)結(jié)構(gòu)體變量中成員的偏移量必須是成員大小的整數(shù)倍(0被認為是任何數(shù)的整數(shù)倍)?
? ? ?(2)結(jié)構(gòu)體大小必須是所有成員大小的整數(shù)倍,也即所有成員大小的公倍數(shù)。
例子1:
struct stru1 ?
{ ?
? ? ?int a; ?//start address is 0
? ? ?char b; ?//start address is 4
? ? ?int c; ?//start address is 8
};
PS:用sizeof求該結(jié)構(gòu)體的大小,發(fā)現(xiàn)值為12。int占4個字節(jié),char占1個字節(jié),結(jié)果應該是9個字節(jié)才對啊,為什么呢?這個例子中前兩個成員的偏移量都滿足要求,但第三個成員的偏移量為5,并不是自身(int)大小的整數(shù)倍。編譯器在處理時會在第二個成員后面補上3個空字節(jié),使得第三個成員的偏移量變成8。結(jié)構(gòu)體大小等于最后一個成員的偏移量加上其大小,上面的例子中計算出來的大小為12,滿足要求。
例子2:
struct stru2 ?
{ ?
? ? ? int i; ?//start address is 0
? ? ? short m; ?//start address is 4
};
PS:成員i的偏移量為0;成員m的偏移量為4,都不需要調(diào)整。但計算出來的大小為6,顯然不是成員m大小的整數(shù)倍。因此,編譯器會在成員m后面補上2個字節(jié),使得結(jié)構(gòu)體的大小變成8從而滿足第二個要求。
例子3、4:
?struct stru3 ?
{ ??
? ? ? ?char i; ?//start address is 0?
? ? ? ?int m; ? //start address is 4
? ? ? ?char n; ?//start address is 8
}; ?
struct stru4 ?
{ ?
? ? ? ?char i; ?//start address is 0
? ? ? ?char n; ?//start address is 1
? ? ? ?int m; ?//start address is 4
?};?
雖然結(jié)構(gòu)體stru3和stru4中成員都一樣,但sizeof(struct stru3)的值為12而sizeof(struct stru4)的值為8。
由此可見,結(jié)構(gòu)體類型需要考慮到字節(jié)對齊的情況,不同的順序會影響結(jié)構(gòu)體的大小。
四、 對于嵌套的結(jié)構(gòu)體,需要將其展開。對結(jié)構(gòu)體求sizeof時,上述兩種原則變?yōu)?#xff1a;
? ? ? ?(1)展開后的結(jié)構(gòu)體的第一個成員的偏移量應當是被展開的結(jié)構(gòu)體中最大的成員的整數(shù)倍。
? ? ? ?(2)結(jié)構(gòu)體大小必須是所有成員大小的整數(shù)倍,這里所有成員計算的是展開后的成員,而不是將嵌套的結(jié)構(gòu)體當做一個整體。
例子1:
struct stru5 ?
{ ?
? ? ? short i; ?
? ? ? struct ??
? ? ? { ?
? ? ? ? ? ?char c; ?
? ? ? ? ? ?int j; ?
? ? ? } tt; ??
? ? ? int k; ?
};
結(jié)構(gòu)體stru5的成員tt.c的偏移量應該是4,而不是2。整個結(jié)構(gòu)體大小應該是16。
例子2:
struct stru6 ?
{ ?
? ? ? char i; ?
? ? ? struct ??
? ? ? { ?
? ? ? ? ? ?char c; ?
? ? ? ? ? ?int j; ?
? ? ? } tt; ??
? ? ? char a; ?
? ? ? char b; ?
? ? ? char d; ?
? ? ? char e; ?
? ? ? int f; ?
};
結(jié)構(gòu)體tt單獨計算占用空間為8,而stru6的sizeof則是20,不是8的整數(shù)倍,這說明在計算sizeof(stru6)時,將嵌套的結(jié)構(gòu)體ss展開了,這樣stu6中最大的成員為tt.j,占用4個字節(jié),20為4的整數(shù)倍。如果將tt當做一個整體,結(jié)果應該是24了。
五:另一個特殊的例子是結(jié)構(gòu)體中包含數(shù)組,其sizeof應當和處理嵌套結(jié)構(gòu)體一樣,將其展開,如下例子:
struct array ?
{ ?
? ? float f; ?
? ? char p; ?
? ? int ?arr[3]; ?
};
其值為20。float占4個字節(jié),到char p時偏移量為4,p占一個字節(jié),到int arr[3]時偏移量為5,擴展為int的整數(shù)倍,而非int arr[3]的整數(shù)倍,這樣偏移量變?yōu)?,而不是12。結(jié)果是8+12=20,是最大成員float或int的大小的整數(shù)倍。
測試環(huán)境:vc++6.0
測試代碼:
?
運行結(jié)果:
?
總結(jié)
以上是生活随笔為你收集整理的sizeof()计算结构体的大小的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成都欢乐谷鬼屋要钱吗
- 下一篇: Shell export命令