iOS - 結(jié)構(gòu)體內(nèi)存分配

問題來源面試題:CGPoint在內(nèi)存中如何分配?

CGPoint在OC中是一個結(jié)構(gòu)體,結(jié)構(gòu)體一般采用內(nèi)存對齊的方式分配桐腌。
1疾层、結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址的偏移量都是這個成員大小的整數(shù)倍纷铣,如果有需要卵史,編譯器會在成員之間加上填充字節(jié)。
2搜立、結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬成員大小的整數(shù)倍以躯。
3、結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除啄踊。
4忧设、對于結(jié)構(gòu)體成員屬性中包含結(jié)構(gòu)體變量的復(fù)合型結(jié)構(gòu)體,在確定最寬基本類型成員時社痛,應(yīng)當(dāng)包括復(fù)合類型成員的子成員见转。但在確定復(fù)合類型成員的偏移位置時則是將復(fù)合類型作為整體看待。
5蒜哀、總結(jié):結(jié)構(gòu)體的大小等于最后一個成員的偏移量加上其大小再加上末尾的填充字節(jié)數(shù)目斩箫,即:sizeof(struct) = offsetof( last item) + sizeof (last item) + sizeof( trailing padding)

例1:

struct fs{
    int i;
    char c;
    int x;
};

第1個成員相對結(jié)構(gòu)體首地址的偏移量為0,是成員int i(長度為4)的整數(shù)倍撵儿。
第2個成員相對結(jié)構(gòu)體首地址的偏移量為4乘客,是成員char c (長度為1)的整倍。(因為結(jié)構(gòu)體總大小為結(jié)構(gòu)體最寬成員大小的整數(shù)位淀歇,所以如果此結(jié)構(gòu)體只有這兩個成員的話易核,會在char c后添加3個填充字節(jié),但現(xiàn)在有3個成員浪默,所以不需要填充牡直。)
第3個成員相對結(jié)構(gòu)體首地址的偏移量為5,不是成員int x 的整數(shù)倍纳决,所以在x前(或者說是c之后)填充3個字節(jié)碰逸,以使x的偏移量達(dá)到8而成為4的整數(shù)倍。所以這個結(jié)構(gòu)體占內(nèi)存大小為4+1+3+4阔加。

例2:成員個數(shù)與每個成員類型都一個饵史,只不過順序不一樣,占內(nèi)存大小就不一樣胜榔。

struct fang {
    char a;     //補(bǔ)0   偏0   長1
    int i;      //補(bǔ)3   偏4   長8
    double d;   //補(bǔ)0   偏8   長16
};              //總長 16

struct fang1 {
    char a;     //補(bǔ)0   偏0   長1
    double d;   //補(bǔ)7   偏8   長16
    int i;      //補(bǔ)0   偏16  長20   20不是8整數(shù)倍胳喷,補(bǔ)4
};              //總長 24

例3:復(fù)合型結(jié)構(gòu)體

struct dou {
    int a;      //補(bǔ)0   偏0   長4
    CGFloat b;  //補(bǔ)4   偏8   長16     16是8整數(shù)倍
};              //總長 16
typedef struct dou dou;

struct dou1 {
    char a;     //補(bǔ)0   偏0   長1
    dou dou;    //補(bǔ)7   偏8   長24     24是8整數(shù)倍,
};              //總長 24
typedef struct dou1 dou1;

對齊設(shè)置

#pragma pack(n) //編譯器將按鈕N個字節(jié)對齊夭织,設(shè)置結(jié)構(gòu)體最寬成員大锌月丁(與實際最寬成員大小取小)尊惰。即結(jié)構(gòu)體最終長度是n的整數(shù)倍奴饮。
#pragma pack() //取消自定義對齊方式纬向。
#pragma pack(puch,1) //把原來對齊方式保存起來择浊,并設(shè)置新的對齊方式戴卜。
#pragma pack(pop) //恢復(fù)之前保存的的對齊狀態(tài)
Expected #pragma pack parameter to be '1', '2', '4', '8', or '16'
預(yù)期的#pragma pack參數(shù)為'1','2'琢岩,'4'投剥,'8'或'16'

#pragma pack(push)
#pragma pack(1)
//相當(dāng)于
#pragma pack(puch,1)

demo

struct A{           //結(jié)構(gòu)體長度按成員最大長度(8)對齊
    char A2;        //補(bǔ)0   偏0   長1
    long A1;        //補(bǔ)7   偏8   長16
    int A3;         //補(bǔ)0   偏16  長20   20不是8整數(shù)倍,補(bǔ)4
};                  //總長24
typedef struct A A;

#pragma pack(1)     //設(shè)置結(jié)構(gòu)體長度按1對齊
struct B{
    char A2;        //補(bǔ)0   偏0   長1
    long A1;        //補(bǔ)0   偏1   長9
    int A3;         //補(bǔ)0   偏9   長13   13是1整數(shù)倍
};                  //總長13
typedef struct B B;

#pragma pack(push)  //將按1對齊的設(shè)置保存担孔。
#pragma pack(2)     //設(shè)置新的對齊方式江锨,結(jié)構(gòu)體長度按2對齊
struct C{
    char A2;        //補(bǔ)0   偏0   長1
    long A1;        //補(bǔ)1   偏2   長10
    int A3;         //補(bǔ)0   偏10  長14    14是2的整數(shù)倍
};                  //總長14
typedef struct C C;

#pragma pack(4)     //設(shè)置新的對齊方式,結(jié)構(gòu)體長度按4對齊
struct D{
    char A2;        //補(bǔ)0   偏0   長1
    long A1;        //補(bǔ)3   偏4   長12
    int A3;         //補(bǔ)0   偏12  長16    16是4整數(shù)倍
};                  //總長16
typedef struct D D;

#pragma pack(16)    //設(shè)置新的對齊方式糕篇,按16對齊啄育。但實際成員最大長度為8,所以還是按8對齊。
struct E{
    char A2;        //補(bǔ)0   偏0   長1
    long A1;        //補(bǔ)7   偏8   長16
    int A3;         //補(bǔ)0   偏16  長20   20不是8整數(shù)倍拌消,補(bǔ)4
};                  //總長24
typedef struct E E;

#pragma pack(pop)   //恢復(fù)之前保存的對齊方式挑豌,按1對齊
struct F{
    char A2;
    long A1;
    int A3;
};                  //總長13
typedef struct F F;


#pragma pack()      //恢復(fù)系統(tǒng)默認(rèn),按成員最大長度(8)對齊
struct G{
    char A2;
    long A1;
    int A3;
};                  //總長24
typedef struct G G;

設(shè)置對齊方式之后的內(nèi)存計算
1墩崩、當(dāng)設(shè)置的對齊長度小于當(dāng)前成員長度時氓英,成員偏移量是成員長度的整數(shù)倍。
2鹦筹、當(dāng)設(shè)置的對齊長度大于當(dāng)前成員長度铝阐,并小于最長成員長度時,成員偏移量是設(shè)置的對齊長度的整數(shù)倍铐拐。
3徘键、當(dāng)設(shè)置的對齊長度大于最長成員長度時,成員成員偏移量按當(dāng)前成員的實際大小對齊遍蟋。
4吹害、當(dāng)設(shè)置的對齊長度小于實際最長成員長度時,結(jié)構(gòu)體長度為設(shè)置的對齊長度的整數(shù)倍匿值。
5赠制、當(dāng)設(shè)置的對齊長度大于或等于實際最長成員長度時,結(jié)構(gòu)體長度為實際最長成員長度的整數(shù)倍挟憔。

為什么要對齊

現(xiàn)代計算機(jī)中內(nèi)存空間都是按照byte劃分的钟些,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定類型變量的時候經(jīng)常在特定的內(nèi)存地址訪問绊谭,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列政恍,而不是順序的一個接一個的排放,這就是對齊达传。
對齊的作用和原因:各個硬件平臺對存儲空間的處理上有很大的不同篙耗。一些平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取迫筑。比如有些架構(gòu)的CPU在訪問一個沒有進(jìn)行對齊的變量的時候會發(fā)生錯誤,那么在這種架構(gòu)下編程必須保證字節(jié)對齊.其他平臺可能沒有這種情況,但是最常見的是如果不按照適合其平臺要求對數(shù)據(jù)存放進(jìn)行對齊宗弯,會在存取效率上帶來損失脯燃。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設(shè)為32位系統(tǒng))如果存放在偶地址開始的地方蒙保,那么一個讀周期就可以讀出這32bit辕棚,而如果存放在奇地址開始的地方,就需要2個讀周期邓厕,并對兩次讀出的結(jié)果的高低字節(jié)進(jìn)行拼湊才能得到該32bit數(shù)據(jù)逝嚎。顯然在讀取效率上下降很多。


作者:Erice_e
來源:CSDN
原文:https://blog.csdn.net/erice_e/article/details/72851219
版權(quán)聲明:本文為博主原創(chuàng)文章详恼,轉(zhuǎn)載請附上博文鏈接补君!
本文參考來源也是https://blog.csdn.net/erice_e/article/details/72851219,在此非常感謝昧互。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挽铁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子硅堆,更是在濱河造成了極大的恐慌屿储,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渐逃,死亡現(xiàn)場離奇詭異够掠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茄菊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門疯潭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人面殖,你說我怎么就攤上這事竖哩。” “怎么了脊僚?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵相叁,是天一觀的道長。 經(jīng)常有香客問我辽幌,道長增淹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任乌企,我火速辦了婚禮虑润,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘加酵。我一直安慰自己拳喻,他們只是感情好哭当,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冗澈,像睡著了一般钦勘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渗柿,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天个盆,我揣著相機(jī)與錄音,去河邊找鬼朵栖。 笑死,一個胖子當(dāng)著我的面吹牛柴梆,可吹牛的內(nèi)容都是我干的陨溅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼绍在,長吁一口氣:“原來是場噩夢啊……” “哼门扇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起偿渡,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤臼寄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后溜宽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吉拳,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年适揉,在試婚紗的時候發(fā)現(xiàn)自己被綠了留攒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡炼邀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剪侮,到底是詐尸還是另有隱情拭宁,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布杰标,位于F島的核電站,受9級特大地震影響驻仅,放射性物質(zhì)發(fā)生泄漏登渣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一嬉愧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喉前,春花似錦见咒、人聲如沸论颅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽推励。三九已至肉迫,卻和暖如春稿黄,著一層夾襖步出監(jiān)牢的瞬間陵珍,已是汗流浹背寝杖。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工亿卤, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留秆乳,地道東北人。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓钻哩,卻偏偏與公主長得像屹堰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子街氢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355