深入理解__block修饰符的底层实现原理

在介绍今天的博客之前,你应该了解,block的三大类型,block的变量捕获机制,哪些情况下是NSMallcBlock,这些内容我前面的博客都有介绍的非常清楚,相信你看了会有很多收获.

通过这篇博客的学习,你将会了解到:

__block它当修饰符的时候,它的底层到底是怎么实现的.

首先看下面的代码:

这里为什么去修改变量的值会报错,大家知道吗?这时候我们去把当前的main.m文件转成c++文件,因为我们知道oc的底层就是c/c++,然后是汇编语言,然后是机器语言,可以通过下面的命令在终端执行:(注意age=20注释,不然转不了)

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

我们想在一个函数里面修改另一个函数的age值,那是不是非常不可能啊,而上面的func_0里面访问的age是之前编译器里面存储的age,跟那个变量没有任何关系,要改也只能改block里面的age,所以我们上面那么写就是有问题.

如果我们在参数前面加一个static参数就不会报错了!请看下图

这里就不说为什么了,因为我们知道static它底层实现是传的是*age,也就是存的是地址值,所以我们只要拿到这个地址,可以随便修改这个变量

重点来了

请看下面的代码,我用__block来当作修饰符如下:

为什么这里用__block就是没有问题的呢?我们还是转成c++代码看一下底层的实现:

这里很清楚,只要我用__block修饰变量,就会吧变量包装成对象,上面能看到是结构体,这个非常清楚,至于为啥__forwarding访问后面我会再说

下面我来解释一下*__forwarding这个是什么东西.请看下面,是我把多余的删了的(大家可以对照原来的删一下多余的代码,便于我们观看):

下面的框框我只是删除了强制转换的代码,是一样的

这个赋值非常明显__forwarding赋值的就是&age,sizeof就是当前的结构体有多大,就是赋值size,而且最下面那个框框,他自己定义的age会传给第二个参数&age,赋值给*__forwarding,所以__Block_byref_age_0它的地址就是*__forwarding,这个也非常清楚

再看一下block内部也会把&age这个值传给age这个值(这个就不截图了,直接可以看得到 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实现就能看出赋值)

请看下面的代码:

这种会不会报错?答案是不会,因为我并没有修改它,我只是在用它.

相信到此大家都会清楚:block存储着这个结构体的内存地址的值,修改的时候,会通过内存地址找到这个结构体,然后修改这个值

到此为止:__block修饰符修饰的变量 为什么block能修改,相信已经很清楚

总结:

1.__block可以用于解决block内部无法修改auto变量值的问题

2.__block不能修饰全局变量、静态变量(static)(大家自己尝试,会报错)

3.编译器会将__block包装成一个对象


接下来可能有些人有点疑惑的就是如果我 NSLog(@"%p",&age);这个age的地址到底是哪个地址?如下

这个age到底是哪个的?

如下:

下面我们就来证明一下这个问题,这个思路我之前的博客有,就是把底层实现的结构体,之前拿过来用

从这里我们可以看出,它并不是block里面存储的age的地址值,这2个值并不是一样,我可以告诉大家,它访问的就是age里面那个age=10的那个age地址,你看下图,我来证明

首先你要知道:大age结构体的地址值,就是它第一个元素的地址值,所以0x0000000101cb92a0就是age结构体里面的_isa的地址.这个要清楚

这里很清楚的证明了,确实是age结构体里面的那个age的值

接下来博客我会介绍Block的__block其他的知识点,来继续探讨block

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容