原文:https://blog.csdn.net/IT_Quanwudi/article/details/80527154
?//結(jié)構(gòu)體大小花履,存在內(nèi)存對齊問題
例如:
①:我們先定義一個結(jié)構(gòu)體A加酵,并將其初始地址設(shè)為100
我們普通認為徙硅,其內(nèi)存申請應(yīng)該這樣申請泳叠,a先申請1個字節(jié)大小空間壤躲,b再申請4個字節(jié)大小空間泼诱,結(jié)構(gòu)體A?共5個字節(jié)苛谷。
如圖:
而實際情況卻非如此:
那我們來看看結(jié)構(gòu)體真正的內(nèi)存申請情況:
因為計算機讀取數(shù)據(jù)時,一般標(biāo)準(zhǔn)化4個4個字節(jié)讀取成箫,所以為了節(jié)約時間展箱,我們浪費3個字符大小的內(nèi)存地址,以空間換取時間蹬昌。
所以我們可以找出規(guī)律計算結(jié)構(gòu)體的大小混驰,以①為例:
②:
結(jié)構(gòu)體大小:和①規(guī)則相同皂贩,②的結(jié)構(gòu)體大小=(1+1)+2+4=8個字節(jié)
結(jié)構(gòu)體內(nèi)存申請情況:
③:
結(jié)構(gòu)體大衅苷ァ:和①②規(guī)則相同,③的結(jié)構(gòu)體大小=(1+1)+2+(1+3)+4 = 12個字節(jié)
結(jié)構(gòu)體內(nèi)存申請情況:
④:
結(jié)構(gòu)體大忻魉ⅰ:本身按照以上規(guī)則婴栽,③的結(jié)構(gòu)體大小應(yīng)該=(1+3)+4+2 = 10個字節(jié)
但是運行后,結(jié)果不匹配辈末,正確答案為12個字節(jié)
?
現(xiàn)在我們來看看看結(jié)構(gòu)體真正的內(nèi)存申請情況:
這是按照以上規(guī)則愚争,畫出來的內(nèi)存圖映皆,看似沒錯,可結(jié)果卻不是12個字節(jié)准脂。
現(xiàn)在我們來考慮一下假設(shè)結(jié)構(gòu)體數(shù)組的存在:
struct ?E ?arr[2];
這時arr[1]的地址可能會出現(xiàn)這種情況:
這時候計算機以標(biāo)準(zhǔn)4個4個讀取時劫扒,會在第三個綠色框框處出現(xiàn)問題,讀取失敗狸膏,不是我們需要的值沟饥。
所以我們?yōu)榱吮苊膺@個情況,我們會給arr[1]結(jié)尾出補上兩個字符湾戳,就不會出現(xiàn)讀取錯誤了贤旷。
結(jié)構(gòu)體內(nèi)存申請情況,如圖:
這時我們回頭看④:我們會發(fā)現(xiàn)結(jié)構(gòu)體大小?=(1+3)+4+2+2 = 12個字節(jié)
我們可以找出規(guī)律計算結(jié)構(gòu)體的大小時避免出現(xiàn)以上問題:
就是在計算出結(jié)構(gòu)體大小時砾脑,用所得值對結(jié)構(gòu)體內(nèi)最大的成員大小取余幼驶,看是否==0;
如果韧衣!=0盅藻,我們給補上一個合適大小的內(nèi)存,讓取余==0?畅铭。
不過在實際工作操作時氏淑,一般會直接在結(jié)構(gòu)體上補上一個空白成員并注釋。
如:
最后我們總結(jié)一下結(jié)構(gòu)體內(nèi)存對齊的規(guī)則:
①:每一行和前面行總和比硕噩,不能被整除假残,則補上。
②:算出總共大小后和單個最大比炉擅,不能被整除辉懒,則補上。
我們結(jié)束前用兩個結(jié)構(gòu)體來驗證我們的對齊規(guī)則谍失。
①:
用對齊規(guī)則來計算:①:4+8=12?眶俩;②:單個最大為int a或者int c都為4個字節(jié),12%4==0快鱼。
結(jié)果正確
將上圖展開仿便,可得:
②:
用對齊規(guī)則來計算:①:8+4=12?;②:單個最大為double a為8個字節(jié)攒巍,
12%8!=0,所以補上4個字節(jié),(12+4)%8==0
結(jié)果為16荒勇,正確柒莉。