结构体内存对齐详解
目錄
前言
代碼示例
結(jié)構(gòu)體內(nèi)存對(duì)齊規(guī)則
畫(huà)圖解題
為什么存在內(nèi)存對(duì)齊
如何設(shè)計(jì)結(jié)構(gòu)體
修改默認(rèn)對(duì)齊數(shù)
結(jié)語(yǔ)
前言
結(jié)構(gòu)體內(nèi)存對(duì)齊問(wèn)題是結(jié)構(gòu)體中非常重要的知識(shí)點(diǎn),本文此進(jìn)行詳細(xì)的總結(jié)。
代碼示例
以上代碼中,結(jié)構(gòu)體成員變量一樣,但是順序不一樣,導(dǎo)致兩個(gè)結(jié)構(gòu)體所占內(nèi)存大小不同,這是為什么呢?
結(jié)構(gòu)體內(nèi)存對(duì)齊規(guī)則
1.第一個(gè)成員在結(jié)構(gòu)體變量偏移量為0的地址處。
2.其他成員變量要對(duì)齊到某個(gè)數(shù)字(對(duì)齊數(shù))的整數(shù)倍的地址處。
對(duì)齊數(shù) = 編譯器默認(rèn)的對(duì)齊數(shù)與該成員大小的較小值。
3.結(jié)構(gòu)體總大小為最大對(duì)齊數(shù)的整數(shù)倍(每個(gè)成員變量都有一個(gè)對(duì)齊數(shù))。
4.如果嵌套了結(jié)構(gòu)體,嵌套的結(jié)構(gòu)體對(duì)齊到自己最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有所有最大的對(duì)齊數(shù)的整數(shù)倍(包含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))。
畫(huà)圖解題
這個(gè)規(guī)則有點(diǎn)抽象,接下來(lái)畫(huà)圖示例。
?
為什么存在內(nèi)存對(duì)齊
1.平臺(tái)原因
不是所有硬件可以訪(fǎng)問(wèn)任意地址處上的任意數(shù)據(jù),某些平臺(tái)只能在某些地址處讀取特定類(lèi)型數(shù)據(jù),否則會(huì)硬件異常。
2.性能原因
數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能在自然邊界上對(duì)齊
原因在于,為了訪(fǎng)問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪(fǎng)問(wèn);而對(duì)于對(duì)齊的內(nèi)存,處理器僅需要一次訪(fǎng)問(wèn)。
如何設(shè)計(jì)結(jié)構(gòu)體
為了使結(jié)構(gòu)體占用的內(nèi)存小一點(diǎn),我們應(yīng)該經(jīng)可能讓占用空間小的內(nèi)存集中在一起,如有兩個(gè)char、兩個(gè)int、兩個(gè)double類(lèi)型的數(shù)據(jù),我們應(yīng)該以char char int int double double double這樣的順序排列結(jié)構(gòu)體成員變量,減少內(nèi)存的浪費(fèi)。
修改默認(rèn)對(duì)齊數(shù)
我使用的是vs2019的編譯器,默認(rèn)的對(duì)齊數(shù)是8,如果結(jié)構(gòu)體在對(duì)齊方式不合適的時(shí)候,可以自己更改默認(rèn)對(duì)齊數(shù)。這時(shí)候需要在程序開(kāi)頭使用 #pragma pack(設(shè)置的默認(rèn)對(duì)齊數(shù))。
結(jié)語(yǔ)
本文到此結(jié)束,希望讀者有所收獲,謝謝閱覽。
總結(jié)