深度解析結構體類型地址偏移量相關問題

Q1:什麼是偏移量?linux

A:結構體變量中成員的地址和結構體變量地址之差。能夠用offsetof(type, member)宏來肯定成員的實際位置(定義於stddef.h),其中type是結構體類型,member是成員名。可知:第一個成員的偏移量爲0,最後一個成員的偏移量加上最後一個成員的大小卻不必定等於結構體大小(先賣個關子=。。=)。windows

Q2:什麼是地址對齊?數組

A:結構體成員是按照聲明的順序存儲在連續的內存空間中,而結構體成員的類型不必定相同,系統在存儲結構體時不是像數組同樣將各個成員大小簡單相加,而須要考慮地址對齊問題。測試

先來簡單看一個例子:spa

  

Q3:上述兩種形式的結構體大小是否相同?blog

A:不相等,雖然結構體成員相同,可是因爲聲明順序不一樣致使地址偏移量不一樣。具體而言第一個結構體大小爲16,第二個爲24。ip

   

 

Q4:結構體存儲時地址對齊,編譯器須要遵循什麼原則?內存

A:兩條原則:編譯器

1.結構體變量中成員的偏移量必須是成員大小的整數倍;編譯

2.結構體大小必須是全部成員大小的整數倍,即全部成員大小的公倍數。

對照上述兩條原則,回過來看上述兩個結構體大小是否是清楚明白了?Student1很好理解,Student2中scores成員偏移量爲16,加上自身大小4後爲20,因爲20不是8的整數倍,去最小公倍數24爲整個結構體大小。(最後一個成員的偏移量加上最後一個成員的大小卻不必定等於結構體大小=。。=)

 

-------------------------------------------我是一條可愛的分割線-------------------------------------------------------

增長點難度,再來看一個例子:

  

你們思考一下結構體Student3的大小?結構體ss偏移量?結構體ss大小爲8,若是將ss看成一個總體Student3大小是否是24?

測試結果倒是:

Q5:出現結構體嵌套時,怎麼計算結構體大小?

A:上述兩個原則須要修改一下:

1.展開後的結構體的第一個成員的偏移量(嵌套的結構體偏移量)應當是被展開的結構體中最大成員的整數倍;

2.結構體大小必須是全部成員大小的整數倍,這裏計算的是展開後的成員,而不是將嵌套的結構體看做一個總體。

 

總結與反思:瞭解結構體存儲方式後,咱們該怎麼作才能充分利用內存,減小邊界對齊帶來的空間損失?

1.重排結構體成員聲明列表,讓那些對邊界要求最嚴格(大)的成員首先出現,對邊界要求最弱(小)的成員最後出現;

2.在考慮程序的可讀性和可維護性的前提下,能夠把相關聯的成員放在一塊兒而不用考慮列表順序問題,不然參考1;

3.在程序聲明幾百個甚至幾千個結構體時,減小內存的浪費要比程序的可讀性更爲急迫,這時能夠經過增長註釋來提升可讀性。

 

tip:如何給結構體變量分配空間由編譯器決定,以上代碼均在linux/GCC下編譯,windows/VC也是如此,其餘平臺可能有不一樣的處理方式。

相關文章
相關標籤/搜索