深入理解__block修飾符的底層實(shí)現(xiàn)原理

在介紹今天的博客之前,你應(yīng)該了解,block的三大類型,block的變量捕獲機(jī)制,哪些情況下是NSMallcBlock,這些內(nèi)容我前面的博客都有介紹的非常清楚,相信你看了會(huì)有很多收獲.

通過(guò)這篇博客的學(xué)習(xí),你將會(huì)了解到:

__block它當(dāng)修飾符的時(shí)候,它的底層到底是怎么實(shí)現(xiàn)的.

首先看下面的代碼:

這里為什么去修改變量的值會(huì)報(bào)錯(cuò),大家知道嗎?這時(shí)候我們?nèi)グ旬?dāng)前的main.m文件轉(zhuǎn)成c++文件,因?yàn)槲覀冎纎c的底層就是c/c++,然后是匯編語(yǔ)言,然后是機(jī)器語(yǔ)言,可以通過(guò)下面的命令在終端執(zhí)行:(注意age=20注釋,不然轉(zhuǎn)不了)

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp

我們想在一個(gè)函數(shù)里面修改另一個(gè)函數(shù)的age值,那是不是非常不可能啊,而上面的func_0里面訪問(wèn)的age是之前編譯器里面存儲(chǔ)的age,跟那個(gè)變量沒(méi)有任何關(guān)系,要改也只能改block里面的age,所以我們上面那么寫就是有問(wèn)題.

如果我們?cè)趨?shù)前面加一個(gè)static參數(shù)就不會(huì)報(bào)錯(cuò)了!請(qǐng)看下圖

這里就不說(shuō)為什么了,因?yàn)槲覀冎纒tatic它底層實(shí)現(xiàn)是傳的是*age,也就是存的是地址值,所以我們只要拿到這個(gè)地址,可以隨便修改這個(gè)變量

重點(diǎn)來(lái)了

請(qǐng)看下面的代碼,我用__block來(lái)當(dāng)作修飾符如下:

為什么這里用__block就是沒(méi)有問(wèn)題的呢?我們還是轉(zhuǎn)成c++代碼看一下底層的實(shí)現(xiàn):

這里很清楚,只要我用__block修飾變量,就會(huì)吧變量包裝成對(duì)象,上面能看到是結(jié)構(gòu)體,這個(gè)非常清楚,至于為啥__forwarding訪問(wèn)后面我會(huì)再說(shuō)

下面我來(lái)解釋一下*__forwarding這個(gè)是什么東西.請(qǐng)看下面,是我把多余的刪了的(大家可以對(duì)照原來(lái)的刪一下多余的代碼,便于我們觀看):

下面的框框我只是刪除了強(qiáng)制轉(zhuǎn)換的代碼,是一樣的

這個(gè)賦值非常明顯__forwarding賦值的就是&age,sizeof就是當(dāng)前的結(jié)構(gòu)體有多大,就是賦值size,而且最下面那個(gè)框框,他自己定義的age會(huì)傳給第二個(gè)參數(shù)&age,賦值給*__forwarding,所以__Block_byref_age_0它的地址就是*__forwarding,這個(gè)也非常清楚

再看一下block內(nèi)部也會(huì)把&age這個(gè)值傳給age這個(gè)值(這個(gè)就不截圖了,直接可以看得到?GDblock block = ((void(*)())&__main_block_impl_0((void*)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_age_0 *)&age,570425344));就是這段代碼找__main_block_impl_0實(shí)現(xiàn)就能看出賦值)

請(qǐng)看下面的代碼:

這種會(huì)不會(huì)報(bào)錯(cuò)?答案是不會(huì),因?yàn)槲也](méi)有修改它,我只是在用它.

相信到此大家都會(huì)清楚:block存儲(chǔ)著這個(gè)結(jié)構(gòu)體的內(nèi)存地址的值,修改的時(shí)候,會(huì)通過(guò)內(nèi)存地址找到這個(gè)結(jié)構(gòu)體,然后修改這個(gè)值

到此為止:__block修飾符修飾的變量 為什么block能修改,相信已經(jīng)很清楚

總結(jié):

1.__block可以用于解決block內(nèi)部無(wú)法修改auto變量值的問(wèn)題

2.__block不能修飾全局變量、靜態(tài)變量(static)(大家自己嘗試,會(huì)報(bào)錯(cuò))

3.編譯器會(huì)將__block包裝成一個(gè)對(duì)象


接下來(lái)可能有些人有點(diǎn)疑惑的就是如果我?NSLog(@"%p",&age);這個(gè)age的地址到底是哪個(gè)地址?如下

這個(gè)age到底是哪個(gè)的?

如下:

下面我們就來(lái)證明一下這個(gè)問(wèn)題,這個(gè)思路我之前的博客有,就是把底層實(shí)現(xiàn)的結(jié)構(gòu)體,之前拿過(guò)來(lái)用

從這里我們可以看出,它并不是block里面存儲(chǔ)的age的地址值,這2個(gè)值并不是一樣,我可以告訴大家,它訪問(wèn)的就是age里面那個(gè)age=10的那個(gè)age地址,你看下圖,我來(lái)證明

首先你要知道:大age結(jié)構(gòu)體的地址值,就是它第一個(gè)元素的地址值,所以0x0000000101cb92a0就是age結(jié)構(gòu)體里面的_isa的地址.這個(gè)要清楚

這里很清楚的證明了,確實(shí)是age結(jié)構(gòu)體里面的那個(gè)age的值

接下來(lái)博客我會(huì)介紹Block的__block其他的知識(shí)點(diǎn),來(lái)繼續(xù)探討block

如果覺(jué)得我寫得對(duì)您有所幫助,請(qǐng)關(guān)注我上遥,我會(huì)持續(xù)更新??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辣恋,一起剝皮案震驚了整個(gè)濱河市模软,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌底靠,老刑警劉巖暑中,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳄逾,死亡現(xiàn)場(chǎng)離奇詭異雕凹,居然都是意外死亡枚抵,警方通過(guò)查閱死者的電腦和手機(jī)明场,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門苦锨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)舟舒,“玉大人秃励,你說(shuō)我怎么就攤上這事〗远” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵滋早,是天一觀的道長(zhǎng)杆麸。 經(jīng)常有香客問(wèn)我浪感,道長(zhǎng),這世上最難降的妖魔是什么揭斧? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任讹开,我火速辦了婚禮旦万,結(jié)果婚禮上成艘,老公的妹妹穿的比我還像新娘淆两。我一直安慰自己秋冰,他們只是感情好踱葛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布尸诽。 她就那樣靜靜地躺著盯另,像睡著了一般鸳惯。 火紅的嫁衣襯著肌膚如雪叠萍。 梳的紋絲不亂的頭發(fā)上苛谷,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天腹殿,我揣著相機(jī)與錄音锣尉,去河邊找鬼自沧。 笑死拇厢,一個(gè)胖子當(dāng)著我的面吹牛旺嬉,可吹牛的內(nèi)容都是我干的厨埋。 我是一名探鬼主播邪媳,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荡陷!你這毒婦竟也來(lái)了雨效?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤废赞,失蹤者是張志新(化名)和其女友劉穎徽龟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唉地,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡据悔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耘沼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片极颓。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖躯肌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嫡丙,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布盼砍,位于F島的核電站睬捶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜座韵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一黔帕、第九天 我趴在偏房一處隱蔽的房頂上張望侣背。 院中可真熱鬧厦取,春花似錦虾攻、人聲如沸澡为。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绽媒,已是汗流浹背猎提。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工贞谓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晕城。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓择吊,卻偏偏與公主長(zhǎng)得像粤攒,于是被迫代替她去往敵國(guó)和親盔几。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容