新建一个 Command Line
项目
main.m
文件代码如下:
#import
typedef void(^MyBlock)(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
int age = 17;
MyBlock block = ^{
NSLog(@"age = %d", age);
};
age = 18;
block();
}
return 0;
}
输出当然是:
age = 17
打开终端,进入main.m文件所在文件夹
输入命令:
xcrun -sdk iphoneos clang -arch arm64 -w -rewrite-objc main.m
会得到一个文件:main.cpp
打开文件,使用快捷键:command + 方向下键
足足有33835
行!
main
函数被展开成这样:
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
typedef void(*MyBlock)(void);
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int age;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int flags=0) : age(_age) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int age = __cself->age; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_tp_mwb8pcp17p72nqrynqllp1s80000gn_T_main_49d6a6_mi_0, age);
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
int age = 17;
MyBlock block = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age));
age = 18;
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
return 0;
}
block 创建时
MyBlock block = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age));
age
是值传递
所以,外部修改age
不会影响block里面的age
#import
typedef void(^MyBlock)(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
__block int age = 17;
MyBlock block = ^{
NSLog(@"age = %d", age);
};
age = 18;
block();
}
return 0;
}
在age
前面加上__block
后
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
typedef void(*MyBlock)(void);
struct __Block_byref_age_0 {
void *__isa;
__Block_byref_age_0 *__forwarding;
int __flags;
int __size;
int age;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_age_0 *age; // by ref
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_age_0 *age = __cself->age; // bound by ref
NSLog((NSString *)&__NSConstantStringImpl__var_folders_tp_mwb8pcp17p72nqrynqllp1s80000gn_T_main_26f1f5_mi_0, (age->__forwarding->age));
}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {
_Block_object_assign((void*)&dst->age, (void*)src->age, 8/*BLOCK_FIELD_IS_BYREF*/);
}
static void __main_block_dispose_0(struct __main_block_impl_0*src) {
_Block_object_dispose((void*)src->age, 8/*BLOCK_FIELD_IS_BYREF*/);
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
__attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 17};
MyBlock block = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_age_0 *)&age, 570425344));
(age.__forwarding->age) = 18;
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
return 0;
}
此时,多了一个__Block_byref_age_0
结构体
__block
修饰的变量
展开成了一个__Block_byref_X_Y
结构体
X 是 变量名
Y 是 第几个
age 变量,变成了,__Block_byref_age_0
结构体
block 在创建时
传入的是这个结构体的引用
而且在函数__main_block_func_0
里面
编译器也给了注释:bound by ref
__Block_byref_age_0 *age = __cself->age; // bound by ref
在未加入__block
之前
是这样的:bound by copy
int age = __cself->age; // bound by copy
所以,这次能修改成功了
https://github.com/xjh093/JHKeyboard