序言
- Objective-C是一門動(dòng)態(tài)性比較強(qiáng)的編程語言,跟C、C++等語言有著很大的不同
- Objective-C的動(dòng)態(tài)性是由Runtime API來支撐的
- Runtime API提供的接口基本都是C語言的,源碼由C\C++\匯編語言編寫
位運(yùn)算和共用體
位運(yùn)算
程序中的所有數(shù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的跨释。位運(yùn)算說穿了侯谁,就是直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作洪燥。
C++提供了6種位運(yùn)算符來進(jìn)行位運(yùn)算操作:
- & 按位與
- | 按位或
- ^ 按位異或
- ~ 按位取反
- << 左移(左邊消失贾富,右邊補(bǔ)0)
- >> 右移(右邊消失蓝撇,左邊補(bǔ)符號(hào)位)
位運(yùn)算的操作數(shù)是整數(shù)類型或字符型.
1.按位與&運(yùn)算
相同為一
& 運(yùn)算常常用來將某變量的某些位清0
& 也常用于二進(jìn)制取位操作
2.按位或|運(yùn)算
有一則一
|運(yùn)算通常用于二進(jìn)制特定位上的強(qiáng)制置1
3.按位異或^運(yùn)算
^運(yùn)算通常用于對(duì)二進(jìn)制的特定一位進(jìn)行取反操作
共用體
共用體把幾種不同數(shù)據(jù)類型的變量存放在同一塊內(nèi)存里。共用體中的變量共享同一塊內(nèi)存缭裆。
定義共用體類型變量的一般形式:
union 共用體名
{
成員列表
}變量列表;
union的主要特征有
- union中可以定義多個(gè)成員键闺,union的大小由最大的成員的大小決定;
- union成員共享同一塊大小的內(nèi)存幼驶,一次只能使用其中的一個(gè)成員艾杏;
- 對(duì)union某一個(gè)成員賦值,會(huì)覆蓋其他成員的值(但前提是成員所占字節(jié)數(shù)相同盅藻,當(dāng)成員所占字節(jié)數(shù)不同時(shí)只會(huì)覆蓋相應(yīng)字節(jié)上的值购桑,比如對(duì)char成員賦值就不會(huì)把整個(gè)int成員覆蓋掉,因?yàn)閏har只占一個(gè)字節(jié)氏淑,而int占四個(gè)字節(jié))勃蜘;
- union量的存放順序是所有成員都從低地址開始存放的。
一 isa詳解
- 要想學(xué)習(xí)Runtime假残,首先要了解它底層的一些常用數(shù)據(jù)結(jié)構(gòu)缭贡,比如isa指針
- 在arm64架構(gòu)之前,isa就是一個(gè)普通的
指針
辉懒,存儲(chǔ)著Class阳惹、Meta-Class對(duì)象的內(nèi)存地址
- 從arm64架構(gòu)開始,對(duì)isa進(jìn)行了優(yōu)化眶俩,變成了一個(gè)
共用體(union)
結(jié)構(gòu)莹汤,還使用位域
來存儲(chǔ)更多的信息
- isa結(jié)構(gòu)體
/** isa_t 結(jié)構(gòu)體 */
union isa_t {
Class cls;
uintptr_t bits;
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 33;
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 19;
};
};
實(shí)例代碼如下 - 一定需要用真機(jī)進(jìn)行調(diào)試
#import <Foundation/Foundation.h>
@interface CSPerson : NSObject
@end
創(chuàng)建一個(gè)對(duì)象并且斷點(diǎn)調(diào)試,輸出 isa 值
接下來我們創(chuàng)建一些關(guān)聯(lián)對(duì)象和弱引用對(duì)象
isa參數(shù)詳解
nonpointer
:
0颠印,代表普通的指針纲岭,存儲(chǔ)著Class、Meta-Class對(duì)象的內(nèi)存地址
1线罕,代表優(yōu)化過止潮,使用位域存儲(chǔ)更多的信息has_assoc
:是否有設(shè)置過關(guān)聯(lián)對(duì)象,如果沒有钞楼,釋放時(shí)會(huì)更快has_cxx_dtor
:是否有C++的析構(gòu)函數(shù)(.cxx_destruct)喇闸,如果沒有,釋放時(shí)會(huì)更快shiftcls
:存儲(chǔ)著Class询件、Meta-Class對(duì)象的內(nèi)存地址信息magic
:用于在調(diào)試時(shí)分辨對(duì)象是否未完成初始化weakly_referenced
:是否有被弱引用指向過仅偎,如果沒有,釋放時(shí)會(huì)更快deallocating
:對(duì)象是否正在釋放extra_rc
:表示該對(duì)象的引用計(jì)數(shù)值雳殊,實(shí)際上是引用計(jì)數(shù)值減 1橘沥,例如,如果對(duì)象的引用計(jì)數(shù)為 10夯秃,那么 extra_rc 為 9座咆。如果引用計(jì)數(shù)大于 10,則需要使用到下面的 has_sidetable_rc仓洼。has_sidetable_rc
:當(dāng)對(duì)象引用計(jì)數(shù)大于 10 時(shí)介陶,則has_sidetable_rc 的值為 1,那么引用計(jì)數(shù)會(huì)存儲(chǔ)在一個(gè)叫 SideTable 的類的屬性中色建,這是一個(gè)散列表哺呜。
為什么要&ISA_MASK來獲取類或元類的地址
因?yàn)閺腶rm64位開始,isa里面存儲(chǔ)各種信息箕戳,是一個(gè)共用體某残,其中shiftcls
33位才是用來存放地址国撵。通過&ISA_MASK就可以將33位的地址值取出來。
無論是實(shí)例對(duì)象玻墅,還是類對(duì)象介牙,還是元類對(duì)象,他們的地址最后一位要么是0澳厢,要么是8环础,因?yàn)樗麄兊牡刂肥?code>isa &
ISA_MASK
,又因?yàn)?code>ISA_MASK最后3位都是0剩拢,所以導(dǎo)致他們的地址最后3位也永遠(yuǎn)是0线得,所以最后一位要么是0(0000 0000)
,要么是8(0000 1000)
徐伐。
本文主要參考MJ老師的教案贯钩,非常感謝MJ老師。
項(xiàng)目連接地址 - runtime_union_mask
關(guān)于runtime更多文章請看如下鏈接
iOS-runtime-API詳解+使用
iOS Runtime原理及使用
iOS - runtime如何通過selector找到對(duì)應(yīng)的 IMP地址(分別考慮類方法和實(shí)例方法)
iOS - Runtime之面試題詳解一
iOS-runtime之面試題詳解二
iOS runtime的使用場景-實(shí)戰(zhàn)篇