美文网首页
C高阶3:变量分类

C高阶3:变量分类

作者: jdzhangxin | 来源:发表于2019-04-14 11:12 被阅读0次

    1. 本地变量/局部变量

    1.1 本地变量/局部变量是什么?

    在大括号内定义的变量就是本地变量/局部变量。

    1.2 本地变量/局部变量有什么特点?

    1. 本地变量是定义在代码块内的,可以定义在函数的块内,可以定义在语句的块内。
    for(int i=0;i<10;++i){
        printf("%d ",i);
    }
    printf("%d ",i);
    

    可以定义在一个随意的大括弧里面。

    {
        int n = 0;
        printf("%d ",n);
    }
    printf("%d ",n);
    
    1. 程序进入块前,内部变量不存在,离开时失效
    2. 块外定义的变量,块内仍然有效。

    函数的每次运行,都会产生一个独立的变量空间,在这个空间中的变量,是函数这次运行独有的。

    • 定义在函数内部的变量就是本地变量
    • 参数也是本地变量

    1.3 本地变量/局部变量初始化

    1. 本地变量不会默认初始化
    2. 参数在进入函数时被初始化。

    本地变量/局部变量的生存期和作用域都是在大括号内。

    2. 全局变量

    2.1 全局变量是什么?

    定义在函数外面的变量称为全局变量

    int n;
    int main(){
        int m;
        printf("n=%d\m=%d\n",n,m);
    }
    

    2.2 全局变量有什么特点?

    全局变量有全局的生存周期和作用域。

    1. 不属于任何函数。
    2. 所有函数内部都可以使用。
    int n;
    int func(){
        printf("in func n = %d\n",n);
        // n = n*2;
    }
    int main(){
        scanf("%d",&n);
        func();
        printf("in main n = %d\n",n);
    }
    

    2.3 全局变量初始化

    1. 没有初始化的全局变量会自动初始化为0
    2. 只能用编译时刻已知的值初始化全局变量。
    3. 初始化发生在main()前。
    int n = 2;
    int m = n;
    double  s = sqrt(n); 
    int main(){
        printf("n = %d,m = %d,s = %f",n,m,s);
    }
    

    2.4 同名隐藏

    如果函数内部存在与全局变量同名的变量,则全局变量被隐藏。

    int n = 10;
    int main(){
        int n = 1;
        printf("n = %d\n",n);
    }
    

    3. 全局静态变量

    3.1 全局静态变量是什么?

    在全局变量前加上关键字static

    static int n;
    int main(){
        int m;
        printf("n=%d\m=%d\n",n,m);
    }
    

    3.2 全局变量与全局静态变量区别

    1. 若程序由一个源文件构成时,全局变量与全局静态变量没有区别。
    2. 若程序由多个源文件构成时,全局变量与全局静态变量不同:全局静态变量使得该变量成为定义该变量的源文件所独享,即:全局静态变量对组成该程序的其它源文件是无效的。
    3. 具有外部链接的静态,可以在所有源文件里调用,除了本文件,其他文件可以通过extern的方式引用。

    4. 本地静态变量

    4.1 静态本地变量是什么?

    在本地变量定义时加上static变成静态本地变量。

    4.2 静态本地变量有什么特点?

    当函数离开时,静态本地变量会继续存在并保存其值。

    int inc(){
        static int n = 1;
        n = n + 1;
        return n;
    }
    int main(){
        printf("%d\n",inc());
        printf("%d\n",inc());
        printf("%d\n",inc());
    }
    

    静态本地变量的初始化在第一次进入函数时执行,以后进入函数会保持离开的值。
    静态本地变量是特殊的全局变量,具有全局生存周期和局部作用域。

    5. 总结

    5.1 变量的作用域和生命期

    • 作用域
      变量或函数在运行时候的 有效作用范围 。
    • 生命期
      变量或函数在运行时候的没被销毁回收的存活时间。
    No. 分类 作用域 生命期
    1 局部变量 所在代码块内 所在函数结束
    2 全局变量 所有文件内 程序执行结束
    3 静态局部变量 所在代码块内 程序执行结束
    4 静态全局变量 当前文件内 程序执行结束
    5 普通函数 所有文件内 -
    6 静态函数 当前文件内 -

    6. static关键字小结:

    static在C语言里面既可以修饰变量,也可以修饰函数。

    • static变量:

      1. 静态局部变量:在函数中定义的,生命周期是整个源程序,但是作用域和局部变量没区别。
        只能在定义这个变量的函数范围内使用,而且只在第一次进入这个函数时候被初始化,之后的初始化会跳过,并保留原来的值。退出这个函数后,尽管这个变量还在,但是已经不能使用了。

      2. 静态全局变量:全局变量本身就是静态存储的,但是静态全局变量和非静态全局变量又有区别:

        1. 全局变量:变量的作用域是整个源程序,其他源文件也可以使用,生命周期整个源程序。
        2. 静态全局变量:变量的作用域范围被限制在当前文件内,其他源文件不可使用,生命周期整个源程序。
    • static函数(内部函数):
      只能被当前文件内的其他函数调用,不能被其他文件内的函数调用,主要是区别非静态函数(外部函数)。

    不对外公开的函数和全局变量
    在函数前面加上static就使它成为只能所在编译文件中使用的函数。
    在全局变量前加上static使它成为只能所在编译文件中使用的全局变量。

    7. 最佳实践

    7.1 不要返回本地变量的指针

    1. 返回本地变量的地址是危险的。
    2. 返回全局变量或静态本地变量的地址是安全的。
    3. 返回函数内的动态内存是安全的,但注意要记得释放。
    4. 最好的做法是返回传入的指针。

    7.2 慎用静态变量

    不要使用全局变量在函数间传递参数和结果。
    尽量避免使用全局变量。
    使用全局变量和静态本地变量的函数是不可重入的,是线程不安全的。

    • 如何解决返回局部数据的问题?
    #include <stdio.h>
    #include <stdlib.h>
    void print_array(int arr[],int n){
        for(int i=0;i<n;++i){
            printf("%d ",arr[i]);
        }
        printf("\n");
    }
    int* scanf_array(int* n){
        scanf("%d",n);
        int* arr = (int*)malloc(*n*sizeof(int));
        for(int i=0;i<*n;++i){
            scanf("%d",&arr[i]);
        }
        return arr;
    }
    int main(){
        int n;
        int *arr = scanf_array(&n);
        print_array(arr,n);
        free(arr);
    }
    

    相关文章

      网友评论

          本文标题:C高阶3:变量分类

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