block的底层实现
来源:互联网 发布:godaddy转阿里云 编辑:程序博客网 时间:2024/04/28 00:35
1、我们都会使用 block ,但是它真正是如何工作的呢?换句话说block的本质是什么?
看下列实例,想想程序的结果:
int main(int argc, const char * argv[]) { int a = 10; __block int b = 20; void (^block)() = ^(){ printf("a = %d\n",a); printf("b = %d\n",b); }; a = 50; b = 30; block();
程序的结果是: a = 10 , b = 30;
这个结果可能大家都知道 ,那么为什么会出现这样的情况呢?很多人都会说 ,b前面加了__block所以他的值可以改变 ,a没加所以不能改变 。这只是表象,接下来我们就研究一下他的block的本质。
2、探究block的底层原理,打开终端 ,把目录切换到当前main.m所在的路径下,我们需要把这个 main.m 文件 编程成c++ 的文件 main.cpp.
输入终端命令: clang -rewrite-objc main.m
生成一个main.cpp文件 ,打开它,但是你要做好心理准备,这个 文件十万多行。
3、找到下列代码
int main(int argc, const char * argv[]) { int a = 10; //__attribute__((__blocks__(byref))) __Block_byref_b_0 b = {(void*)0,(__Block_byref_b_0 *)&b, 0, sizeof(__Block_byref_b_0), 20}; void (*block)() = &__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a, (__Block_byref_b_0 *)&b, 570425344); a = 50; (b.__forwarding->b) = 30; ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block); return 0;}}
分析:
3.1、分析这个block参数
&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a, &b, 570425344)
//block -> 实质 函数指针
//__main_block_func_0 指针
//__main_block_desc_0_DATA 地址 block 的描述数据
//a 普通变量
//&b b地址 b -> __Block_byref_b_0类型
//b 变量 就会被封装成 __Block_byref_b_0 结构体类型
3.2、分析struct __Block_byref_b_0 结构体
struct __Block_byref_b_0 { void *__isa; //当前对象的指针 __Block_byref_b_0 *__forwarding; //当前这种结构体类型的指针 __forwarding存对象自己地址 int __flags; //标记 int __size; //结构体的大小 int b; //变量 };
3.3、函数的初始化
struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; int a; // 10 __Block_byref_b_0 *b; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, __Block_byref_b_0 *_b, int flags=0) : a(_a), b(_b->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; //执行的那段代码 打印 Desc = desc; } }
3.4、__block_impl结构体分析
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; };
3.5、__main_block_func_0
__main_block_func_0(struct __main_block_impl_0 *__cself) { //地址 直接访问属性 __Block_byref_b_0 *b = __cself->b; // bound by ref int a = __cself->a; // bound by copy printf("a = %d\n",a); printf("b = %d\n",(b->__forwarding->b)); }
在上述的代码中我们可以理解为: 变量a传入的是值,变量b传入的是地址。__block 把b强转成一个结构体指针。
blcok的本质就是一个函数指针 ,也可以说是一个指向结构体的指针。
- block的底层实现
- block的底层实现(二)
- iOS中block实现的底层探究
- iOS中block实现的底层探究
- block底层实现原理
- iOS 底层实现 - Block
- block底层实现(一)
- OC 中的block的使用与它的实现底层
- OC中block的底层实现和具体运用(转)
- iOS中block实现的底层探究2
- iOS中OC:block底层实现原理
- iOS OC语言: Block底层实现原理
- iOS OC语言: Block底层实现原理
- iOS Block底层实现原理详解
- iOS OC语言: Block底层实现原理
- OC语言: Block底层实现原理
- iOS OC语言: Block底层实现原理
- 小码哥-(知其所以然一)OC中block的底层实现和具体运用
- RID Agents
- nginx 负载均衡
- LA 4513 Stammering Aliens
- [2097]:Sky数
- win7下卸载linux系统(不用windows光盘)
- block的底层实现
- 在 Xcode 7 中安装 Alcatraz(可用)
- 日常总结 windows的cmd窗口进入指定文件夹(即目录)和cmd默认窗口大小设置
- 微型嵌入式操作系统对比
- Linux内核源代码解析——IP切碎了又粘好
- 切换Fragment,改变Toolbar menu的显示样式
- Redis的Client设计
- MariaDB 5.5.34 QPS bug手记
- quick-cocos2d-x(一)开发环境配置