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

2022-09-24 12:26:11

????????关注后回复 “进群” ,拉你进程序员交流群????????

转自:掘金  GDCoder

https://juejin.cn/post/6942796652717539364

在介绍今天的博客之前,你应该了解,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的值

转自:掘金  GDCoder

https://juejin.cn/post/6942796652717539364

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击????卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

  • 作者:iOS_开发
  • 原文链接:https://blog.csdn.net/olsQ93038o99S/article/details/115534686
    更新时间:2022-09-24 12:26:11