Block对变量的作用(二)

2017-11-21  本文已影响19人  凉白开0072

常见的变量有哪些?

在C语言中常见的变量如下:

Block对这几种变量的作用

第一篇文章(你真的知道Block是什么吗?)中OC代码打印结果如下:

Block 外 global_i = 2,static_global_j = 3,static_k = 4,val = 5
Block 中 global_i = 3,static_global_j = 4,static_k = 5,val = 4

Block外打印结果很正常,Block中会发现以下两个问题:

  1. val 在block内部不能改变,报错提示要加上__block,为什么?
  2. val这个自动变量的结果却是不变的,为什么呢?

从第一篇文章(你真的知道Block是什么吗?)的C++代码分析可得:

  1. 全局变量global_i,静态全局变量static_global_j,他们有与程序相同的生命周期,而且作用域很广,因此在程序运行中随时可以拿到,他们最终的结果并不意外
  2. 自动变量val 和静态变量static_k
    __main_block_impl_0这个结构体的构造函数中,我们可以看到,接收局部变量val的是int _val,接收静态变量的是 int *_static_k,然后在看__main_block_func_0这个函数取出这两个变量怎么取的,int *static_k = __cself->static_k; int val = __cself->val;,从这里我们就能看出,自动变量val是值传递,而静态变量static_k是地址传递(指针),这就解释了,为什么Block中打印的自动变量没变化的原因了.
  3. 至于在block内部改变自动变量会报错:必须加__block的原因
    可以用作用域来解释,从2.中我们知道,自动变量传递到block中的仅仅是自动变量的值而已,并没有把自动变量传进去,然而我们却在block内部拿到自动变量对其操作,很显然是拿不到这个变量的,所以必然错误,至于加__block的原理后面会讲解.

Block中改变自动变量的两种方式

  1. 传递内存地址指针到Block中。
  2. 改变存储区方式(__block)。
    先看第一种,从上面的结论我们看到,自动变量是值传递的,那么,我们可以设想一下,如果我们的局部变量不是基本数据类型,而是指针呢? 当外部的局部变量变化时,block中拿到的是变化后的,还是变化前的?此时在block中能修改局部变量吗?还会报错吗?
    测试代码:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    int a = 1 ;
    int *p = &a;
    void (^myBlock)(void) = ^{
     //这里可以修改了,并不会报错__block了
        *p = 3;
        NSLog(@"Block中 a = %zd",*p);
    };
    a = 2;
    NSLog(@"Block外 a = %zd",a);
    
    myBlock();
    
    return 0;
}

打印结果如下:

Block外 a = 2
Block中 a = 3
可以看到,如果自动变量是指针,那么在block中就可以改变该自动变量的值

结论

上一篇下一篇

猜你喜欢

热点阅读