美文网首页C语言
19-static和extern关键字2-对变量的作用

19-static和extern关键字2-对变量的作用

作者: Andy_Livings | 来源:发表于2020-06-08 13:18 被阅读0次

一、在Java中,全局变量的定义没有严格的位置规定

全局变量可以定义在类的最前面,也可以定义在类的最尾端,也就说一个方法可以访问在它之后定义的变量。


image

可以看到,第4行定义的test方法可以访问第8行定义的变量a,这是完全没有问题的。

二、在C语言中,全局变量定义的位置是有限制的

默认情况下,一个函数不可以访问在它后面定义的全局变量

image

在第4行定义的main函数中尝试访问第9行定义的变量a,编译器直接报错了。

解决这个错误的话,有2种办法:

第1种办法:将变量a定义在main函数的前面
image

这样做编译器就不会找你麻烦了。

第2种办法:在main函数前面对变量a进行提前声明

也就是让main函数知道变量a的存在就行了,至于变量a定义在哪个位置,main函数不用管。

  • 完整的变量声明需要用extern关键字
image

第3行是对变量a进行声明,第10行是定义变量a,再次强调,声明和定义是两码事。在第6行操作的就是第10行定义的变量a。

注意:你不能省略第10行的定义,只留下第3行的声明,因为extern是用来声明一个已经定义过的变量。

三、重复定义同一个变量

  • 其实,你也可以直接在main函数前面再定义一次a
image

看到这一幕,你可能很惊讶,但编译器是不会报错的。在这种情况下,第3行和第10行的变量a代表着同一个变量。

  • 以此类推,如果我们写了无数遍全局变量int a;,它们代表的都是同一个变量。
image

第3到第6行、第13到第17行的变量a都代表着同一个变量。

  • 还要注意的一点是,我们也可以将全局变量a声明为局部变量后再使用!!!
image

注意:第2、第5、第6、第10行都代表着同一个变量。其实,从第6行a的颜色(浅蓝色)都可以看出,这个a依然是个全局变量。

(这是Xcode的特性,如果在函数内部访问了全局变量,全局变量就会显示浅蓝色,如果函数内部访问的是局部变量,局部变量就显示普通的黑色。当然,不同的开发工具有不同的显示方案)

  • 但是,如果你将第5行的extern去掉,那情况就完全不一样了,相信有编程经验的你都懂得这是什么情况了
image

第2、第10行代表着同一个全局变量,而第5、第6行则是一个局部变量,跟外面的那个全局变量没有半毛钱的关系。其实从第5、6行a的颜色(黑色)都可以看出是个局部变量。

四、不同源文件中的同名变量

前面讲到,你在一个源文件中无论写多少遍全局变量int a;,它们代表的都是同一个变量。还有一个事实,假如在另一个源文件中也有全局变量int a;,那么这两个源文件的所有全局变量int a;都代表着同一个变量。

image image

注意:main.c和test.c中的全局变量a都代表着同一个变量。

我们可以证明一下:

首先,在test.c中定义一个函数来查看a的值

image

然后在main.c的第9行修改a的值为10,然后调用test.c的test函数看看test.c中a的值

image

控制台的输出test.c中a为:10 已经证明了一切。

  • 当然,extern关键字还是适用的,比如:


    QQ20200528-175434.png

上面的两种情况下,test.c和main.c中使用的全局变量a都还是代表着同一个变量

注意了,不可以两个文件的所有全部变量a都用extern,下面的做法是错误的:

QQ20200528-175450.png

因为extern是用来声明一个已经定义过的变量,这两个文件都是在声明变量,没有人定义变量,在链接的时候肯定报错:

image

大致错误意思是:标示符a未定义

五、static关键字

但很多时候,我们并不想让源文件中的全局变量跟其他源文件共享,相当于私有的全局变量,那么你就得用static关键字来定义变量。

image image

这样写完,test.c和main.c的变量a分别代表着不同的变量,它们是没有联系的、互不干扰的。也就是说,main.c无法访问test.c中的变量a,因此在main.c中将a修改为10后,test.c中的a依然为0。输出结果:test.c中a的值为:0

其实static还可以用来修饰局部变量。

  • 因为main.c已经没有权限访问test.c中的变量a了,所以下面的写法是错误的:


    QQ20200528-180202.png

extern是用来声明已经定义过而且能够访问的变量,虽然test.c中有定义过变量a,但是test.c中变量a的作用域是只限于test.c文件,main.c没有访问权限,所以main.c中的extern是废的。

链接的时候报错:标示符a未定义

image

除非main.c自己定义一个变量a,这样子extern才是有效的,不过这时候main.c和test.c中的变量a是分别代表着不同变量

image

六、static和extern的总结

1.extern可以用来声明一个全局变量,但是不能用来定义变量

2.默认情况下,一个全局变量是可以供多个源文件共享的,也就说,多个源文件中同名的全局变量都代表着同一个变量

3.如果在定义全局变量的时候加上static关键字,此时static的作用在于限制该全局变量的作用域,只能在定义该全局变量的文件中才能使用,跟其他源文件中的同名变量互不干扰




七、程序实现

01-static和extern对变量的作用2

void static_and_extern_effects_on_functions_2(void) {
    
    /*
     全局变量分2种:
     外部变量:定义的变量能被本文件和其他文件访问
     1> 默认情况下,所有的全局变量都是外部变量
     1> 不同文件中的同名外部变量,都代表着同一个变量
     
     内部变量:定义的变量只能被本文件访问,不能被其他文件访问
     1> 不同文件中的同名内部变量,互不影响
     
     static对变量的作用:
     定义一个内部变量
     
     extern对变量的作用:
     声明一个外部变量
     
     static对函数的作用:
     定义和声明一个内部函数
     
     extern对函数的作用:
     定义和声明一个外部函数(可以省略)
     */
    
    
    /*
     void test(void);

     // 定义一个外部变量
     //int a; 这么多个a都是代表同一个a
     //int a;
     //int a;
     //int a;
     //int a;

     // 定义一个内部变量
     static int b;

     // 声明一个外部变量
     //extern int a;
     */
    
    
    /*
     // b = 10;
     //test();
     extern int a;
     a = 10;
     
      a = 10;
      test();
      printf("a的值是%d\n", a);
     */
    
    
    /*
     int a;
     static int b;
     void test() {
         printf("b的值是%d\n", b);
         printf("a的值是%d\n", a);
         a = 20;
     }
     */
    
}

02-递归

int recursive_practice_pow2(int b, int n);
void recursive_practice(void) {
    
    /*
     设计一个函数,用来计算b的n次方
     
     递归的2个条件:
     1.函数自己调用自己
     2.必须有个明确的返回值
     */
    
    int c = recursive_practice_pow2(3, 2);
    printf("c = %d\n", c);
}

/*
 recursive_practice_pow2(b, 0) == 1
 recursive_practice_pow2(b, 1) == b == recursive_practice_pow2(b, 0) * b
 recursive_practice_pow2(b, 2) == b * b == recursive_practice_pow2(b, 1) * b
 recursive_practice_pow2(b, 3) == b * b * b == recursive_practice_pow2(b, 2) * b
 
 1> n为0,结果肯定是1
 2> n > 0,recursive_practice_pow2(b, n) == recursive_practice_pow2(b, n-1) * b
 */

int recursive_practice_pow2(int b, int n) {

    if (n <= 0) return 1;
    return recursive_practice_pow2(b, n-1) * b;
}


/*
int recursive_practice_pow2(int b, int n) {
    // 用来保存计算结果
    int result = 1;
    
    //result *= b;
    //result *= b;
    //result *= b;
    //result *= b;
    //....
    
    //n次
    
    for (int i = 0; i < n; i++) {
        
        result *= b;
    }
    
    return result;
}
 */

03-static与局部变量

void static_and_local_variables_test() {
    
    static double pi = 3.14;
    double zc = 2 * pi * 10;
    printf("zc = %f\n", zc);
    
    int a = 0;
    a++;
    printf("a的值是%d\n", a); // 1
    
    /*
     static修饰局部变量:
     1> 延长局部变量的生命周期:程序结束的时候,局部变量才会被销毁
     2> 并没有改变局部变量的作用域
     3> 所有的static_and_local_variables_test函数都共享着一个变量b
     */
    static int b = 0;
    b++;
    printf("b的值是%d\n", b); // 3
}
void static_and_local_variables(void) {
    
    /*
     static修饰局部变量的使用场合:
     1.如果某个函数的调用频率特别高
     2.这个函数内部的某个变量值是固定不变的
     */
    
    for (int i = 0; i < 100; i++) {
        static_and_local_variables_test();
    }
    
    static_and_local_variables_test();
    static_and_local_variables_test();
    static_and_local_variables_test();
}

相关文章

  • 19-static和extern关键字2-对变量的作用

    一、在Java中,全局变量的定义没有严格的位置规定 全局变量可以定义在类的最前面,也可以定义在类的最尾端,也就说一...

  • C语言复习之extern和static

    static和extern关键字对变量的作用 extern1.在main函数前面对变量a进行提前声明。也就是让ma...

  • C++语言基础

    extern关键字作用 1.extern置于函数或者变量前,声明这个函数或变量,可以在本地模块使用,但定义在其它模...

  • 面试题之关键字

    C语言中extern 的作用,extern “c”的作用? ①extern 可以置于变量或者函数前,以标示变量或函...

  • 【C语言学习】extern关键字的作用是什么?

    extern关键字可以用来声明变量和函数作为外部变量或者函数供其它文件使用。 extern声明变量 示例程序: t...

  • extern和static对变量的作用

    1.extern可以用来声明一个全局变量,但是不能用来定义变量,声明可以进行多次,但不能重复定义变量(不使用的时候...

  • iOS 学习笔记, 代码片段

    26, extern关键字 extern关键字主要是声明这个变量已经在其他文件中声明过了(声明全局变量或者函数),...

  • static 和 extern 关键字

    static 和 extern 是c语言中的两个关键字,是用来修饰变量和函数. 1.static和extern修饰...

  • iOS-单例模式

    static修饰变量 修饰全局变量:全局变量的作用域仅限于当前文件内部(不加的话别人使用extern关键字就能从其...

  • static和extern关键字

    static和extern对变量的作用 C语言里的变量分两种:全局变量和局部变量。全局变量又分为外部全局变量和内部...

网友评论

    本文标题:19-static和extern关键字2-对变量的作用

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