int (^bk)(int);
void f1(void)
{
int a=1; //在栈区
static int b=2; //在数据区
__block int c=3; //在栈区,由__block修饰的局部变量会在block代码中复制一份,但这个备份不在常量区,在数据区或堆区
printf("在f1中&a=%p\n",&a); //在f1中&a=0x7fff5fbff84c
printf("在f1中&b=%p\n",&b); //在f1中&b=0x1000010d8
printf("在f1中&c=%p\n",&c); //在f1中&c=0x7fff5fbff840
printf("\n");
bk=^(int x)
{
//代码块将a的值复制了一份放到了栈外,所以代码块真正访问的只是一个a的备份
printf("在bk中a=%d\n",a);
printf("在bk中&a=%p\n",&a); //在bk中&a=0x100104df8
printf("在bk中b=%d\n",b); //在bk中b=2
//c也不在栈上
printf("在bk中&c=%p\n",&c); //在bk中&c=0x100103da8
c=88;
printf("&c=%d\n",c); //&c=88
// a=99;//此处不能修改a的值,因为a备份在代码区或常量区
b=33;
printf("block中修改b值后,b=%d &b=%p\n",b,&b); //b=33
return 0;
};
}
//B用static修饰的变量,在block中可以使用,无地址复制还是原来的地址,无特殊。
//A普通声明的变量,原来在栈区,在block中应用,相当于复制了一份地址在栈外的区域,代码块真正访问的是a的一个备份,在block内部不可以修改,因为a在代码区或常量区
//C用__block声明,开始声明时也在栈区,在block中应用时,会在block的代码块中复制一份,这块地址不在栈区,在数据区或堆区,在block中可以改变C的值,
void f2(void)
{
__block int c=30;//在栈区
printf("在f2中,c=%d,&c=%p\n",c,&c);//在f2中,c=30,&c=0x7fff5fbff848
int(^bk)(int)=^(int x)
{
c=31;
printf("在f2中在bk中,c=%d,&c=%p\n",c,&c);//在f2中在bk中,c=31,&c=0x100602bc8
return 0;
};
//此处访问的c是bk中的c,因为用__block修饰的函数局部变量的本意是让程序跟踪c变量在block中的变化而变化(或者直接使用block中的c)
printf("在f2中,调bk之前,c=%d,&c=%p\n",c,&c);//在f2中,调bk之前,c=30,&c=0x100602bc8
bk(1);
printf("在f2中,调bk之后,c=%d,&c=%p\n",c,&c);//在f2中,调bk之后,c=31,&c=0x100602bc8
}
//用__block声明的变量,本意是让程序跟踪c变量在block中的变化而变化,即使block还没有执行,但是变量C的地址已经改变了。但是C的值没有改变,当block执行完以后,C的值会发生改变,地址和block内部的地址是同一个地址,不在栈区。
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
f1();
bk(4);
f2();
// 在f1中&a=0x7fff5fbff84c
// 在f1中&b=0x1000020d8
// 在f1中&c=0x7fff5fbff840
//
// 在bk中a=1
// 在bk中&a=0x1006029e8
// 在bk中b=2
// 在bk中&c=0x100602068
// &c=88
// block中修改b值后,b=33 &b=0x1000020d8
// 在f2中,c=30,&c=0x7fff5fbff848
// 在f2中,调bk之前,c=30,&c=0x100602bc8
// 在f2中在bk中,c=31,&c=0x100602bc8
// 在f2中,调bk之后,c=31,&c=0x100602bc8
}
return 0;
}