先看两种方式的代码:
- (void)blockDemo1{
__block int num = 10;
int *p = #
NSLog(@"=>%p",p);
// 定义一个block
void (^task)() = ^{
NSLog(@"==>%p-%d",&num,num);
NSLog(@"=>%d",*p);
};
num = 20;
NSLog(@"=>%p",p);
// 执行block
task();
NSLog(@"===>%p-%d",&num,num);
NSLog(@"=>%d",*p);
}
2017-02-21 20:04:00.117 04-Block的面试题[4856:577406] =>0x7fff55e95668
2017-02-21 20:04:00.117 04-Block的面试题[4856:577406] =>0x7fff55e95668
2017-02-21 20:04:00.117 04-Block的面试题[4856:577406] ==>0x600000232958-20
2017-02-21 20:04:00.117 04-Block的面试题[4856:577406] =>10
2017-02-21 20:04:00.117 04-Block的面试题[4856:577406] ===>0x600000232958-20
2017-02-21 20:04:00.118 04-Block的面试题[4856:577406] =>10
- (void)blockDemo1{
int num = 10;
int *p = #
NSLog(@"=>%p",p);
// 定义一个block
void (^task)() = ^{
NSLog(@"==>%p-%d",&num,num);
NSLog(@"=>%d",*p);
};
num = 20;
NSLog(@"=>%p",p);
// 执行block
task();
NSLog(@"===>%p-%d",&num,num);
NSLog(@"=>%d",*p);
}
2017-02-21 20:05:19.534 04-Block的面试题[4877:578778] =>0x7fff5536766c
2017-02-21 20:05:19.534 04-Block的面试题[4877:578778] =>0x7fff5536766c
2017-02-21 20:05:19.534 04-Block的面试题[4877:578778] ==>0x600000055478-10
2017-02-21 20:05:19.534 04-Block的面试题[4877:578778] =>20
2017-02-21 20:05:19.535 04-Block的面试题[4877:578778] ===>0x7fff5536766c-20
2017-02-21 20:05:19.535 04-Block的面试题[4877:578778] =>20
不同点:是基本数据类型前面加了一个”block”
加”block”:
这种情况下,系统在编译block时,发现有个num变量,外部没有用__block修饰,系统会在堆区中创建一个同名同类型的变量,在真正执行代码的时候,如果没有对num进行修改的操作,那么就会直接调用堆区中的num的值,这个值是在编译的时候已经赋给堆区变量的,打印(简单地说这个时候block内部与外部没有任何的关系),当block执行完毕后,调用的num还是之前的栈区中创建的num
加”block”:
这个时候,程序在编译block代码块的时候,发现num是被__block修饰的,就不会上来就在堆区中创建num变量,而是在执行到这里的时候才去按照外部的同名变量去在堆区中创建num,与此同时,会修改外部变量的地址,这个地址是堆区中num的地址,所以在最后打印num的地址,是指向堆区的,因而获取的值也是堆区中num的值