struct
struct可以將一些相關聯的數據打包成一個整體。既然提到了struct那麼肯定就避免不了結構體,結構體的內存對齊。
1. 什麼是結構體?
結構體是一系列類型數據的集合這些數據可能描述了一個物體。
2. 什麼時候會用到結構體?
1. 當內置類型無法滿足用戶需求的時候,沒有合適類型的時候,需要封裝特定的類型
2. 當函數有多個參數時,或者函數的返回值過多的時候,需要封裝特定的類型,將參數打包返回
3. 什麼是結構體內存對齊?爲什麼存在內存對齊?內存對齊的規則是什麼?
編譯器爲程序中的每一個數據單元安排在合適的位置上,從而導致了相同的變量,不同聲明順序的結構體的大小不同。 內存對齊存在的主要原因:
1. 平臺原因:不是所有的硬件平臺都可以訪問任意地址上的任意數據,某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出異常(這個爲什麼會拋出異常,不是很懂)
2. 性能原因:經過內存對齊後,CPU的內存訪問速度大大提升,因爲如果沒有內存對齊的話,CPU在訪問一個數據時可能會進行多次訪問然後拼接在一起。
結構體的內存對齊規則: (看下面的規則)
1. 結構體的第一個成員存放在與結構體變量偏移量爲0的地址處
2. 結構體的其他成員要對齊到對齊數的整數倍地址處。對齊數:編譯器默認的一個對齊數與該成員大小中的較小值,VS默認的對齊數位8,Linux中默認值爲4
3. 結構體的總大小最最大對齊數的整數倍
4. 如果一個結構體中嵌套了結構體,嵌套的結構體對齊到自己的最大對齊數的整數倍,結構體的大小就是所有最大對齊數(包含嵌套結構體的對齊數)的整數倍
5. 可以通過#pragma pack number設置對齊數
如何知道結構體中某個成員相對於結構體起始位置的偏移量?
//使用offsetof宏
size_t offsetof( structName, memberName )
---------------------
規則一.: 每個成員變量在其結構體內的偏移量都是成員變量類型的大小的倍數。
規則二: 如果有嵌套結構體,那麼內嵌結構體的第一個成員變量在外結構體中的偏移量,是內嵌結構體中那個數據類型大小最大的成員變量的倍數。
規則三: 整個結構體的大小要是這個結構體內數據類型大小最大的成員變量的倍數。如果有內嵌結構體,那麼取內嵌結構體中數據類型大小最大的成員變量作爲計算外結構體整體大小的依據。
例子
typedef struct TEST{ int na; char cb; char cc; int nd; char cf; struct TT{ int ng; long long llh; }tt; char ci; }test;
圖一
如上圖所示,根據規則一,nd在結構體內的位置必須滿足是其自身數據類型大小的整數倍,且倍數要取滿足條件的最小倍數。因爲nd前三個成員變量總大小是6Bytes,nd作爲int類型,其數據類型大小是4Bytes,滿足條件的最小倍數是2,所以nd在結構體中的偏移量是8,故填充2Bytes。
根據規則二,ng作爲內嵌結構體的第一個成員變量,它在外結構體中的偏移量要滿足——其內嵌結構體中最大數據類型大小的倍數。在計算cf偏移量後,當前偏移量是13,而內嵌結構體中最大數據類型爲long long,其大小爲8,ng的偏移量必須是8的倍數,且取大於13的最小倍數,即2。所以ng前要填充3Bytes。
根據規則三,計算完ci後,當前偏移量是33。如果要滿足test結構體的大小是其中最大數據成員類型大小的倍數,在此例中是內嵌結構體的成員變量llh,即8的倍數。所以要填充7Bytes。