美文网首页iOS面试基础知识点
iOS Block学习笔记(一) -- Block变量与C语言函

iOS Block学习笔记(一) -- Block变量与C语言函

作者: brownfeng | 来源:发表于2018-11-02 16:35 被阅读22次

    C语言中的函数与函数指针

    一般我们称Block是匿名函数, 匿名函数就是没有名称的函数, 本文就来梳理Block和C语言函数的联系.

    在C语言中, 函数的声明, 定义和调用如下:

    // 定义函数
    int func(int arg) {
        printf("%d\n", arg);
        return arg;
    };
    
    // 调用函数
    int ret = func(10);
    

    因此,我们看到,调用func函数,必须使用该函数的函数名 --func.

    同时, 我们也可以声明定义一个函数指针变量, 然后用函数指针变量调用函数, 例如:

    // 定义一个函数指针变量
    int (*funcPtr)(int) = &func;
    // 通过函数指针变量调用函数
    int ret = (*funcPtr)(10);
    

    实际,就算使用函数指针去调用函数,也是需要知道原函数的函数名,否则无法获取原函数的地址.

    OC中的Block匿名函数以及Block变量

    现在,OC中我们Block匿名函数的结构如下:

    ^ 返回值类型 参数列表 函数表达式

    同上面的函数类似, Block的声明和定义以及调用如下:

    // Block匿名函数的定义
    ^(int arg){
        return arg;
    };
    
    // Block匿名函数的调用
    int ret = ^(int arg){return arg;}(10);
    
    // 定义一个Block匿名函数变量
    int (^temBlock)(int arg) = ^(int arg){return arg;};
    
    // 通过Block匿名函数变量调用匿名函数
    int ret = temBlock(10);
    

    注意我们一般说的Block, 有时候指Block匿名函数, 有时候指Block匿名函数变量, 要进行区分.后面直接说Block,和Block变量

    为了让我们看的更加清楚, 我们将函数指针变量和block变量卸载一起:

    int func(int arg) {
        return arg;
    };
    
    int (*funcPtr)(int) = &func;
    int ret = funcPtr(10);
    
    int (^tmpBlock)(int arg) = ^(int arg){
        return arg;
    };
    
    int ret = tmpBlock(10);
    

    因此,我们可以看到函数指针类型变量 -- int (*funcPtr)(int)Block类型变量 -- int (^tmpBlock)(int arg) 两个非常相似, Block类型变量仅仅是将声明函数指针类型变量*变为^.

    其他语言中的匿名函数, 我们看到闭包(Closure), lambda等也是匿名函数的别称

    Block变量的用途

    Block变量可以用于如下用途:

    1. 自动变量
    2. 函数参数
    3. 静态变量
    4. 静态全局变量
    5. 全局变量
    

    例如:

    
    //1. 自动变量
    int (^blk)(int) = ^(int arg) {return arg;};
    int (^blk1)(int) = blk;
    int (blk2)(int);
    blk2 = blk1;
    
    //2. 函数参数
    void func(int arg,int (^blk)(int)){
        blk(arg);
    }
    
    //3. 函数返回值
    int (^func())(int){
        return ^(int arg){return arg;};
    }
    

    上面形式看不清楚可以用 typedef来解决该问题:

    typedef int (^blk_t)(int);
    
    void func(int arg,int (^blk)(int)){
        blk(arg);
    }
    void func(int arg, blk_t blk){
        blk(arg);
    }
    
    int (^func())(int){
        return ^(int arg){return arg;};
    }
    
    blk_t func(){
        return ^(int arg){return arg;};
    }
    

    因此Block变量可以像C语言中的其他变量一样使用.

    参考资料

    1. <<Objective-C 高级编程: iOS与OSX多线程和内存管理>>

    相关文章

      网友评论

        本文标题:iOS Block学习笔记(一) -- Block变量与C语言函

        本文链接:https://www.haomeiwen.com/subject/ulycxqtx.html