文档章节

__block的作用和功能

余成海
 余成海
发布于 2016/08/30 10:36
字数 679
阅读 57
收藏 0

哈,好久没写博客了,oschina的编辑器变漂亮啦!!!!!

int val = 0;
void (^blk)(void) =  ^{
    ++val;
};

先看代码,代码这么写的话会编译失败,提示错误:

原因在于,栈上的局部变量无法在block中编辑,block只做了只读拷贝,解决的办法当然是__block修饰啦,但是__block到底有什么作用,编译器遇到__block做了什么处理,这也是面试中常问的问题。

插个问题,考下大家,看看下面的代码输出的结果是什么.大家可以试下

int val = 0;
void (^blkk)(void) =  ^{
    NSLog(@"~~~~~~~%d", val);
};
val++;
blkk();

----------------------------凌乱分割线--------------------------------

上面的结果当然是0,因为在val++之前,block已经对val做了只读拷贝,所以后来修改val和block中的val无关了,再看下下面的代码

__block int val = 0;
void (^blkk)(void) =  ^{
    NSLog(@"~~~~~~~%d", val);
};
val++;
blkk();

结果就变成1了,所以可以看出__block的作用,__block修饰的变量在block中使用时,block不会对变量只读拷贝操作。

简单说,__block说明符类似static、auto、register一样,作用是改变变量的存储区域,它会使得修饰的变量结构化到block的自动变量中去,解释下这句话,就是说val会被存储到block结构中去。看看编译结果就很清楚了

__block int val = 0;
void ^(blk)(void) = ^(val = 1);

上面这段代码通过编译器编译后出来的结果是这样的:

struct __Block_byref_val_0 {
    void *__isa;
    __Block_byref_val_0 *__forwarding;
    int __flags;
    int __size;
    int val;
};

struct __main_block_impl_0 {
    struct __block_impl  impl;
    struct __main_block_desc_0 *Desc;
    __Block_byref_val_0 *val;

    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_val_0 *_val, int flags=0) : val(_val->__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_val_0 *val = __cself->val;
    (val->__forwarding->val) == 1;
}

........

int main()
{
    __Block_byref_val_0 val = {
        0,
        &val,
        0,
        sizeof(__Blcok_byref_val_0),
        0
    };

    blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x2200000);

    return 0;
}

c的代码也是比较好看懂的,可以看到,int val 变成一个结构体了__Block_byref_val_0,在block的结构体中还包含了val。

 

当然大家会想到一个问题,如果有多个block会出现什么情况,同时用到val。会不会出现两个block中的val不一样呢,我们看下代码

__block int val = 0;
void (^blk0)(void) = ^{val = 1};
void (^blk1)(void) = ^{val = 2};

看下转换后的代码:

__Block_byref_val_0 val = {0, 
&val,
0,
sizeof(__block_byref_val_0, 
0)
};

blk0 = &__main_block_impl_0(__main_block,func_0, &__main_block_desc_0_DATA, &val, 0x22000000);
blk1 = &__main_block_impl_1(__main_block,func_0, &__main_block_desc_0_DATA, &val, 0x22000000);

可以看到block赋值了val结构的地址,所以两个block,拥有的是同一块val的数据。这也是编译器把val的结构体定义单独提出来,而不是放到block结构中定义的原因

© 著作权归作者所有

共有 人打赏支持
余成海
粉丝 62
博文 57
码字总数 29577
作品 0
杭州
iOS工程师
私信 提问
OC中的block基础知识

// 1.函数指针专门用来指向C语言的函数的指针(专门用来存储函数名的地址) // 2.选择器是用来存储OC中方法,(存的也是方法名) // 3.block也是专门用来存储方法 (存的是函数体-实现函数功...

鹿微微鹿
2016/03/29
14
0
OC block的第二个作用:协议代理

YTStaff.h #import <Foundation/Foundation.h> //拥有某种能力的对象 @interface YTStaff : NSObject //需要一个block属性 //问:block为什么要使用copy? //答:因为block变量默认是存储在栈...

鹿微微鹿
2016/03/29
21
0
OC中block的作用

Math.h #import <Foundation/Foundation.h> @interface Math : NSObject{ // NSString * _name; } @property(nonatomic, copy) NSString * name; //_name //按给定的方式去计算两个整型数据的......

鹿微微鹿
2016/03/29
96
0
Objective-C中 Block 在iOS在4.0版本的使用

Objective-C中 Block 在iOS在4.0版本的使用 了解何谓block。 了解block的使用方法。 Block 是iOS在4.0版本之后新增的程序语法. 在iOS SDK 4.0之后,Block几乎出现在所有新版的API之中,换句话...

浩浩老师
2015/09/11
228
0
Oracle Internal Event:10200 Consistent Read诊断事件

10200(consistent read buffer status)内部诊断事件可以用于探测一致性读CR(consistent read)块的访问情况,虽然cr读的统计信息可以从v$sysstat或AWR/statspack中获取,但是10200 event还是我...

科技小能手
2017/11/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

GlusterFS的再次节点重置和恢复

采用Ubuntu+ZFS+GlusterFS的存储集群,其中一个节点再次出现故障,gluster volume status显示为N/A状态。 检查网络,发现原来的IP地址 10.1.1.193发生了改变(估计被DHCP重新分派地址了),导...

openthings
26分钟前
5
0
BOM与正则表达式

BOM BOM的全称叫做Browser OjbectModel 浏览器对象模型,它定义了操作浏览器的接口。 BOM对象包括:Window、History、Navigator、Screen和Location。但是由于浏览器厂商的不同,BOM对象的兼容...

Panda-Q
26分钟前
1
0
牵头函数

箭头函数表达式的语法比函数表达式更短,并且没有自己的this,arguments,super或new.target。这些函数表达式更适用于那些本 来需要匿名函数的地方,并且它们不能用作构造函数。 首先:我们先...

wshining
32分钟前
1
0
mysql把一个数据库中的数据复制到另一个数据库中的表 2个表结构相同

首页 问题 全部问题 经济金融 企业管理 法律法规 社会民生 科学教育 健康生活 体育运动 文化艺术 电子数码 电脑网络 娱乐休闲 行政地区 心理分析 医疗卫生 精选 知道专栏 知道日报 知道大数据...

linjin200
33分钟前
1
0
python redis操作

redis命令:http://blog.csdn.net/yhl27/article/details/9936189 python redis: 干货 http://www.cnblogs.com/wangtp/p/5636872.html http://doc.redisfans.com/ http://developer.51cto.......

stys35
33分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部