問題來源面試題: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,在此非常感謝昧互。