對象的創(chuàng)建核心有三步:
-
cls->instanceSize
:計算需要開辟的內(nèi)存空間大小 -
calloc
:申請內(nèi)存,返回地址指針 -
obj->initInstanceIsa
:將 類 與 isa 關(guān)聯(lián)
具體講解可見前兩篇文章:
一、alloc & init底層探索
二、內(nèi)存對齊原則及OC對象內(nèi)存
接下來將對isa
和isa關(guān)聯(lián)類
進(jìn)行解析, 在講解之前先了解下結(jié)構(gòu)體(Struct)
、聯(lián)合體(Union)
和位域
, 下篇進(jìn)入isa與類關(guān)聯(lián)四、isa與類關(guān)聯(lián)的原理
結(jié)構(gòu)體(Struct)
結(jié)構(gòu)體是C語言中一種重要的數(shù)據(jù)類型,該數(shù)據(jù)類型由一組稱為成員(或稱為域,或稱為元素)的不同數(shù)據(jù)組成,其中每個成員可以具有不同的類型。結(jié)構(gòu)體通常用來表示類型不同但是又相關(guān)的若干數(shù)據(jù)。
結(jié)構(gòu)體類型不是由系統(tǒng)定義好的,而是需要程序設(shè)計者自己定義的。C語言提供了關(guān)鍵字struct
來標(biāo)識所定義的結(jié)構(gòu)體類型。
關(guān)鍵字struct
和結(jié)構(gòu)體名
組合成一種類型標(biāo)識符,其地位如同通常的int
、char
等類型標(biāo)識符,其用途就像 int 類型標(biāo)識符標(biāo)識整型變量一樣可以用來定義結(jié)構(gòu)體變量。定義變量以后,該變量就可以像定義的其他變量一樣使用了;
成員
又稱為成員變量
,它是結(jié)構(gòu)體所包含的若干個基本的結(jié)構(gòu)類型,必須用“{}”括起來,并且要以分號結(jié)束,每個成員應(yīng)表明具體的數(shù)據(jù)類型。
struct LGStruct1 {
double a; // 8 (0-7)
char b; // 1 [8 1] (8)
int c; // 4 [9 4] 9 10 11 (12 13 14 15)
short d; // 2 [16 2] (16 17)
}struct1;
內(nèi)存使用符合內(nèi)存對齊原則
聯(lián)合體/共用體(Union)
聯(lián)合體(union)
與結(jié)構(gòu)體(struct)
有一些相似之處。但兩者有本質(zhì)上的不同
。在結(jié)構(gòu)體
中,各成員有各自的內(nèi)存空間
, 一個結(jié)構(gòu)變量的總長度是各成員長度之和
。而在聯(lián)合體
中,各成員共享
一段內(nèi)存空間
, 一個聯(lián)合變量
的長度等于各成員中最長的長度
。
聯(lián)合體是一個結(jié)構(gòu)
- 它的所有成員相對于基地址的偏移量都為0;
- 此結(jié)構(gòu)空間要大到足夠容納最"寬"的成員;
- 其對齊方式要適合其中所有的成員;
聯(lián)合體的內(nèi)存對齊
聯(lián)合體所占空間需要滿足的條件:
- 大小足夠容納最寬的成員;
- 大小能被其包含的所有
基本數(shù)據(jù)類型
的大小所整除。
union U
{
char s[9]; // 9
int n; // 4
double d; // 8
};
復(fù)制代碼聯(lián)合體的大小為 16。
位域
位域定義與結(jié)構(gòu)定義相仿,其形式為:
struct 位域結(jié)構(gòu)名
{
位域列表
};
其中位域列表的形式為:
類型說明符 位域名: 位域長度(占多少位)
例如:
struct bs{
int a:8;
int b:2;
int c:6;
}data;
說明 data 為 bs 變量,共占兩個字節(jié)。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。
對于位域的定義尚有以下幾點說明:
int : 0表示下面出現(xiàn)的類型不能夠再往里面填充。
struct area
{
int a:3;
int:0; //告訴下面,20不能夠放到a的那塊存儲區(qū)域去了
int c:20;
};
結(jié)構(gòu)體大小為4+4=8;如果沒有int:0,大小為4。
int : x 表示占用幾個位,占用部分不可用,但是接下來的位可繼續(xù)往上面填充。
struct area
{
int a:3;
int:4; //表示a和c中間有4位不可用。
int c:20;
};
該結(jié)構(gòu)體大小為4。
如果int:4改為int:10,那么該結(jié)構(gòu)體大小會變?yōu)?。
位域不能跨字節(jié),位域需要跟結(jié)構(gòu)體最長類型對齊,前面的類型應(yīng)自動對齊,然后再進(jìn)行填充。
struct area1
{
char a:6; //向int對齊,擴(kuò)展為32位
char b:3;
int c:22;
};
結(jié)構(gòu)體大小 :8
struct area2
{
char a:6; //向int對齊,擴(kuò)展為32位
char b:3;
int c:21;
};
結(jié)構(gòu)體大小 :4
位域壓縮規(guī)則
- 如果相鄰位域字段的類型相同,且其位寬之和小于這個類型的sizeof大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止;
- 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;
- 如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
- 如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
- 整個結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。