block的实现原理
2015-06-30 18:01
567 查看
block的实现原理
将代码在Xcode中编写后,编译查看结果,test3和test4的结果我想大家都能猜到,基本C语言的一致.
但test1和test2的实现原理是比较重要的,运行后对结果的怎么实现的无法理解.
代码如下:
-------------------------------------------------------------------------- 美丽的分割线 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代码
//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 copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_0,a);
}
//内部两个参数,第一个为保留,第二个为block的字节长度,通过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 ref
NSLog((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 copy
NSLog((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
将代码在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 copy
NSLog((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 ref
NSLog((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 copy
NSLog((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
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- Ruby中使用Block、Proc、lambda实现闭包
- Ruby中的block、proc、lambda区别总结
- Lua中类的实现原理探讨(Lua中实现类的方法)
- 百度工程师讲PHP函数的实现原理及性能分析(一)
- js判断客户端是iOS还是Android等移动终端的方法
- IOS开发环境windows化攻略
- 理解Javascript_11_constructor实现原理
- Objective-C的内省(Introspection)用法小结
- .net平台推送ios消息的实现方法
- C语言kmp算法简单示例和实现原理探究
- 百度工程师讲PHP函数的实现原理及性能分析(三)
- 百度工程师讲PHP函数的实现原理及性能分析(二)
- C++多态的实现及原理详细解析