為什麼存在記憶體對齊?
1、平台原因(移植原因):不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。
2、效能原因:資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。
總的來說,結構體的記憶體對齊是拿空間來換取時間的做法。
1、第乙個成員變數在與結構體變數偏移量為0的位址處。通俗來說,就是結構體中的第乙個成員變數不用考慮對齊。
2、其他成員變數要對齊到某個數字(對齊數)的整數倍位址處。
3、結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍。如果不是整數倍,說明沒有對齊,需要將總大小擴充套件至能整除最大對齊數的位置。
4、如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。(選擇結構體和巢狀的結構體中的最大對齊數里最大的那個值)。
補充說明:
第乙個元素不用對齊,並不代表沒有對齊數,而是不需要。
對齊數=指定的乙個對齊數與該成員大小的較小值。
預設情況下,對齊數為自身的大小。
對齊:其他成員在放入結構體時,其起始偏移量能整除自身對齊數稱為對齊。
指定乙個對齊數:
#pragma pack(1) 只能設1 2 4 8 16 32……2^n。
每個變數對齊數和指定對齊數比較,選擇較小的對齊數,作為該變數的對齊數。
結構體大小測試:
#include #includestruct s1
;struct s2
;struct s3
;struct s4
;int main()
執行結果:
練習:struct b
;struct a
;解答:
對於結構體b的大小,起始偏移量為0,a的大小為1,故自身對齊數為1可以整除。
b的起始偏移量為1,b的對齊數為4,1不能整除4,故需要3個位元組的空間使其對齊。
c的起始偏移量為(1+3+4)8,對齊數為2,8能整除2,故直接加2。最後由規則3,結構體總大小為最大對齊數的整數倍,結構體中b的最大對齊數為4,故最後對齊時再加2,即8+2+2=12,所以結構體b的大小為12。
對於結構體a的大小,結構體a中巢狀結構體b,由規則4:如果巢狀了結構體(b)的情況,巢狀的結構體(b)對齊到自己的最大對齊數的整數倍處,結構體(a)的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。結構體a的大小:1+3+4+3+1+4+12+1+12+3=44。
union 共用體名;
結構體和共用體的區別在於:結構體的各個成員會占用不同的記憶體,互相之間沒有影響;而共用體的所有成員占用同一段記憶體,修改乙個成員會影響其餘所有成員。
結構體占用的記憶體大於等於所有成員占用的記憶體的總和(成員之間可能會存在縫隙),所以聯合占用的記憶體大小也要考慮自身記憶體對齊。共用體使用了記憶體覆蓋技術,同一時刻只能儲存乙個成員的值,如果對新的成員賦值,就會把原來成員的值覆蓋掉。
聯合的占用記憶體的大小計算:只需要整除最大對齊數即可,最後類似根據結構體規則3:結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍。如果不是整數倍,說明沒有對齊,需要將總大小擴充套件至能整除最大對齊數的位置。即可算出聯合的大小。
測試**如下:
#include #includeunion un1
;union un2
;int main()
測試結果:
C語言中關於結構體的記憶體對齊
以前沒太總結,今天看飛卡的書偶然看到的乙個關於嵌入式c結構體的知識,趕緊來記錄下,方便以後忘記了再次查閱。1 自然對齊 兩個原則 1 各個型別偏移量必須是自身所佔位元組數的整數倍。譬如,int佔4位元組,它的偏移量也必須是4的倍數 2 總的大小必須為該結構體中最大記憶體的整數倍,不夠需要補充。對了,...
關於C語言中的結構體對齊
關於c語言中的結構體對齊 1 什麼是位元組對齊 乙個變數占用 n 個位元組,則該變數的起始位址必須能夠被 n 整除,即 存放起始位址 n 0,對於結構體而言,這個 n 取其成員種的資料型別佔空間的值最大的那個。2 為什麼要位元組對齊 記憶體空間是按照位元組來劃分的,從理論上說對記憶體空間的訪問可以從...
C語言中結構體占用記憶體問題
之前對結構體占用記憶體一直很混亂,到底是按照哪個變數型別計算記憶體?還是怎麼計算?下面先看乙個例子 struct str1 str1這個結構體占用的記憶體是多少呢?如果用變數型別直接想加,得到的結果是17,但顯然不是這樣的。這個程式執行的正確結果是24.為什麼呢?因為為了cpu能夠快速訪問,提高訪問...