标签:
在很多的系统方法中都使用的到了block,它的实质是函数指针 void(*block)()
常常用block代替代理
在C中,函数是保存了整个函数的地址入口,直接调用函数执行。
而block,只是调用了一段代码,在合适的时候执行。
Demo:
int a = 10; __block int b = 20; void (^block)() = ^(){ printf("a = %d\n",a); printf("b = %d\n",b); }; a = 50; b = 30; block();
clang -rewrite-objc main.m
int main(int argc, const char * argv[]) { int a = 10; //__block修饰,封装到结构体__Block_byref_b_0 __attribute__((__blocks__(byref))) __Block_byref_b_0 b = {(void*)0,(__Block_byref_b_0 *)&b, 0, sizeof(__Block_byref_b_0), 20}; //传入到结构体struct __main_block_impl_0 的__main_block_impl_0(...){...}中 void (*block)() = (void(*)())&__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; //获取结构体属性FuncPtr。也就是封装后的block方法体。然后传入block实例,执行打印 ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block); return 0; }
--------------拆解:
a>
__attribute__((__blocks__(byref))) __Block_byref_b_0 b = {(void*)0,(__Block_byref_b_0 *)&b, 0, sizeof(__Block_byref_b_0), 20};
参数: (void*)0
(__Block_byref_b_0 *)&b
0
sizeof(__Block_byref_b_0)
20
把b的值 封装到 __Block_byref_b_0结构体中。【__block修饰的值的封装结构体】
struct __Block_byref_b_0 { void *__isa; //当前对象指针 __Block_byref_b_0 *__forwarding; //当前结构体指针,__forwarding 存储自己地址。用__block修饰便执行 int __flags; //标记 int __size; // 结构体大小 int b; // 值 };
b>传递到结构体中的方法里
void (*block)() = (void(*)())&__main_block_impl_0( (void *)__main_block_func_0, &__main_block_desc_0_DATA, a, (__Block_byref_b_0 *)&b, 570425344 );
传递:(void *)__main_block_func_0 // 存储block方法体【是这里的两条打印】,下文的*fp
&__main_block_desc_0_DATA // 地址,block的描述数据
a // 值传递
(__Block_byref_b_0 *)&b //传递 b的地址,结构体包装
570425344
到:block的实例方法
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; //执行的代码 打印。__main_block_func_0 Desc = desc; } }
block内的方法封装到这里
static void __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)); }
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; };
c>
a = 50; (b.__forwarding->b) = 30;
这里的b 是 __Block_byref_b_0 b
在结构体中获得属性__forwarding,并给它指向值 30;
使用__block 和不使用。 一直个传址,一个是传值。
反编译成C++ 后发现,当使用了__block 修饰对象的时候,都会封装成一种类型的结构体。
标签:
原文地址:http://my.oschina.net/u/1184527/blog/500862