block的实现原理

来源:互联网 发布:linux编程基础 编辑:程序博客网 时间:2024/05/20 01:37

block的实现原理

将代码在Xcode中编写后,编译查看结果,test3和test4的结果我想大家都能猜到,基本C语言的一致.
但test1和test2的实现原理是比较重要的,运行后对结果的怎么实现的无法理解.
代码如下:

void test1() {int a = 8;void (^myBlock)() = ^{NSLog(@"a = %d",a);};a = 12;myBlock();}void test2() {__block int a = 8;void (^myBlock)() = ^{NSLog(@"a = %d",a);};a = 12;myBlock();}void test3() {static int a = 8;void (^myBlock)() = ^{NSLog(@"a = %d",a);};a = 12;myBlock();}int a = 8;void test4() {void (^myBlock)() = ^{NSLog(@"a = %d",a);};a = 12;myBlock();}int main(int argc, const char * argv[]) {test4();return 0;}
想要理解block的内部实现原理,我们需要将代码编译成cpp文件.在terminal中以clang -rewrite-objc main.m 指令将其编译生成 main.cpp文件,以下代码是截取重要部分的内容.

--------------------------------------------------------------------------    美丽的分割线  cpp分析部分 ---------------------------------------------------------------

//main函数

int main(int argc, const char * argv[]) {test1();return 0;}

//block的实现部分

//1.从这里开始

重点:

//1.1.a的值被初始化成8
//1.2.被传入myBlock的是a,因此被传入的是a的值8.
//1.3由于传入的是8常量,因此在block中不能给a重新赋值.
//1.4block中传入3个参数,
//1.5注意此时a的值8已传入block中,此时可以理解为:block实现部分已经就绪,只欠西北风了</span>
//1.6重新给a赋值12,这个结赋值不会影响block中的a的值,因为block的参数已经传入了,更新后不会再传入
//1.7执行block代码

void test1() {//1.1 int a = 8;//1.2//1.3//1.4//1.5 void (*myBlock)() = (void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a);//1.6 a = 12;//1.7 ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);}

//2.原先a的值以形参_a的形式传进来,并赋给a,因此block中的a的值为8
    /**
     *  __test1_block_impl_0的实现部分
     *
     *  @param fp       函数指针
     *  @param desc  结构体__test1_block_impl_0的字节长度
     *  @param _a     形参a
     *  @param flags 忽视它
     *
     */

struct __test1_block_impl_0 {struct __block_impl impl;struct __test1_block_desc_0* Desc;int a;__test1_block_impl_0(void *fp, struct __test1_block_desc_0 *desc, int _a, int flags=0) : a(_a) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}};

/**
 *  block函数内部功能
 *
 *  @param __cself 结构体的内部变量的引用
 */

//将__test1_block_impl_0中的a的值传给局部变量a中,将会打印该a的值.

static void __test1_block_func_0(struct __test1_block_impl_0 *__cself) {int a = __cself->a; // bound by copyNSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_0,a);}

//内部两个参数,第一个为保留,第二个为block的字节长度,通过sizeof(struct __test1_block_impl_0)得到值

static struct __test1_block_desc_0 {size_t reserved;size_t Block_size;} __test1_block_desc_0_DATA = { 0, sizeof(struct __test1_block_impl_0)};

//这是block的结构,是个结构体,记住block是个结构体

struct __Block_byref_a_0 {void *__isa;__Block_byref_a_0 *__forwarding; int __flags; int __size; int a;};

--------------------------------------------------------------------------    美丽的分割线   test2分析---------------------------------------------------------------

//================ test2 =================================================================struct __test2_block_impl_0 {struct __block_impl impl;struct __test2_block_desc_0* Desc;__Block_byref_a_0 *a; // by ref__test2_block_impl_0(void *fp, struct __test2_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}};static void __test2_block_func_0(struct __test2_block_impl_0 *__cself) {__Block_byref_a_0 *a = __cself->a; // bound by refNSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_1,(a->__forwarding->a));}static void __test2_block_copy_0(struct __test2_block_impl_0*dst, struct __test2_block_impl_0*src) {_Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}static void __test2_block_dispose_0(struct __test2_block_impl_0*src) {_Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}static struct __test2_block_desc_0 {size_t reserved;size_t Block_size;void (*copy)(struct __test2_block_impl_0*, struct __test2_block_impl_0*);void (*dispose)(struct __test2_block_impl_0*);} __test2_block_desc_0_DATA = { 0, sizeof(struct __test2_block_impl_0), __test2_block_copy_0, __test2_block_dispose_0};void test2() { __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 8};} 

/**
  *  test2与test1的区别在于此,将block中传入的不是a的值,而是a的地址
  *
  *  @param myBlock 函数名
  *  因此在block中可以重新对a进行赋值
  */

void (*myBlock)() = (void (*)())&__test2_block_impl_0((void *)__test2_block_func_0, &__test2_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344); (a.__forwarding->a) = 12; ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);}

只分析了test1和test2,我想test3和test4比较好理解.

--------------------------------------------------------------------------    美丽的分割线   test3和test4 cpp代码,自行分析---------------------------------------------------------------

/================ test3 =================================================================struct __test3_block_impl_0 {struct __block_impl impl;struct __test3_block_desc_0* Desc;int *a;__test3_block_impl_0(void *fp, struct __test3_block_desc_0 *desc, int *_a, int flags=0) : a(_a) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}};static void __test3_block_func_0(struct __test3_block_impl_0 *__cself) {int *a = __cself->a; // bound by copyNSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_2,(*a));}static struct __test3_block_desc_0 {size_t reserved;size_t Block_size;} __test3_block_desc_0_DATA = { 0, sizeof(struct __test3_block_impl_0)};void test3() { static int a = 8; void (*myBlock)() = (void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, &a); a = 12; ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);}//================ test4 =================================================================int a = 8;struct __test4_block_impl_0 {struct __block_impl impl;struct __test4_block_desc_0* Desc;__test4_block_impl_0(void *fp, struct __test4_block_desc_0 *desc, int flags=0) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}};static void __test4_block_func_0(struct __test4_block_impl_0 *__cself) {NSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_3,a);}static struct __test4_block_desc_0 {size_t reserved;size_t Block_size;} __test4_block_desc_0_DATA = { 0, sizeof(struct __test4_block_impl_0)};void test4() { void (*myBlock)() = (void (*)())&__test4_block_impl_0((void *)__test4_block_func_0, &__test4_block_desc_0_DATA); a = 12; ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);}

test3是由static声明,test4是全局变量,因此内从中只有一份.

---end


0 0