C语言中的函数-变量的存储方式和生存期-下-学习笔记-21

局部变量的存储类别 (下)

上面我们讲了自动(auto)变量和静态(static)变量,接下来我们将剩下的部分。

寄存器变量

一般情况下,变量(动态变量或静态变量)一般都存放在内存中,当程序需要用到哪个变量的时候,控制器发出一个指令,将内存中该变量的值发送到运算器中,经过运算器进行运算。如果需要存储数据,那就等运算结束后,再从运算器将数据送回内存。
其实还是蛮好理解的,就是从内存拿了数去运算器运算,算完了结果再返回给内存存储。但是如果遇到一些变量频繁的使用,我们就要频繁的执行取了算-算了存这样的操作,比如我们要循环100000次,这样我们每次存取的过程都会非常浪费时间
为了解决这样的问题,程序允许我们将数据存放在 CPU 的寄存器中,需要的时候从寄存器中取数据到运算器就好了。你会发现这还是一个取了算-算了存的过程,怎么会解决我们存取时浪费时间的问题呢?

因为数据在 CPU 寄存器中读取的速度远大于在内存中的速度,就好像从老式软盘升级到了 SSD 固态硬盘。所以我们的存取过程的时间大幅度节省了。

我们称这种存放在CPU寄存器中的变量 叫做寄存器变量,用关键字 register 进行声明。

1
register int name;  //声明一个名叫 name 的寄存器整型变量

随着计算机性能的提高编译器已经能够识别那些经常被频繁调用的变量,并自动将其设置为寄存器变量。所我们只需要了解和认识有这种变量即可

介绍完局部变量的存储类别,我们学习了三种局部变量,三种局部变量分别存储在不同的区域。自动局部变量存储在动态存储区、静态局部变量存储在静态存储区、寄存器局部变量存储在 CPU 寄存器中。

全局变量的存储类别

全局变量都是存放在静态存储区的,所以他们的生存期是固定的,即从程序开始执行到程序结束。但是对于全局变量来说,它需要知道自己的作用域从何处开始,何处结束。
一般来说,外部变量,是从函数外定义的全局变量,全局变量从它声明的那一刻起到本程序的末尾都有效。在这个范围内的各个函数都可以引用全局变量。如果我们需要扩展全局变量的作用域,有以下集中情况。

在一个文件内扩展外部变量的作用域

如果外部变量没有在文件的开头定义,其有效的作用域仅存在与变量定义处到文件结束的这个区间。在定义点之前的函数无法引用该外部变量。
如果我们需要引用定义在下方的外部变量,在引用之前,需要用关键字extern对该变量做外部变量声明。表示把外部变量的作用域扩展到此处。这样外部变量的起始范围就扩大到了从声明处到文件末尾了。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main(){
extern int A,B,C;
int max(int a,int b);
printf("请输入三个数:\n");
scanf("%d %d %d",&A,&B,&C);
printf("这三个数中最大的是%d!\n",max(A,max(B,C)));
}
int A,B,C;
int max(int a, int b){
int big;
big=a>b? a:b;
return (big);
}

上面这个例子我们可以看出,在 main 函数中引用 A、B、C三个全局变量,但是这三个全局变量在 main 函数下面才定义的,为了使 main 函数能够正确是识别和使用这三个变量,我们使用 extern 将这三个变量的作用与扩展到了 main 函数的第一行,这样我们就可以在 main 函数中使用这三个变量了。

我们在使用 extern 的时候,也可以不写类型名,extern int aextern a其实是一样的,因为 extern 不是声明变量,不必说明变量类型,有名字就好了~

将外部变量的作用域扩展到其他文件

我们知道,外部变量的作用范围一般是从定义位置起到该源程序文件的尾部,如果我们需要跨文件使用一个全局变量呢?
例如,我们在 A 文件中定义并使用了 average 这个全局变量,但是这个全局变量的有效作用域只到这个文件的结尾处。如果我们在 B 文件中再次调用 average 这个全局变量,是找不到的,所以,在 B 文件中,我们使用 extern 将 average 变量链接过去。

例子

A.c 文件

1
2
3
4
5
6
#include <stdio.h>
int AGE;
int main(){
scanf("%d",&age);
return 0;
}

B.c 文件

1
2
extern int AGE;
printf("输入的年龄是:%d 岁",AGE);

上面这个例子中,我们在 A 文件中声明了 AGE 全局变量,然后在 B 文件中,使用 extern 将 A 文件中的 AGE 全局变量进行了链接。如果我们的程序有5个这样的文件,那么在其他的4个文件想使用 A 文件中的全局变量的话,都需要在文件头处输入 extern 指令。

extern 的运行逻辑
在系统遇到 extern 时,首先在本文件中找外部变量,如果找到,那就在本文件中扩展该变量的作用域。如果没有找到,那就在其他的文件中找该变量的定义,如果找到了就进行链接,扩展作用域到本文件中,如果没有找到,那就报错。

将外部变量的作用域扩展到本文件中

如果说,我们希望在本文件中的全局变量,不要被其他文件使用。那么我们就需要在定义外部变量时增加一个 static 的声明。

A.c 文件

1
2
3
4
5
6
#include <stdio.h>
static int A;
int main(){
scanf("%d",A);
return 0;
}

B.c 文件

1
2
extern A;
printf("%d",A);

上面的这种方法,B 文件是会报错的,因为在 A 文件中声明全局变量 A 的时候,对变量 A 进行了 static 的声明,所以不能被 B 文件 extern 进行链接。

不要被 static 误解

因为全局变量已经是存放在静态存储区域了,所以,这里再次使用 static 是为了声明这个变量的作用域只限制在该文件中,不被其它文件引用。

我们在多人编写程序时,如果在自己的文件中需要使用全局变量,但又不想影响到其他人的程序,可以在文件中使用静态全局变量,这样就可以只在该源程序文件中使用,也使得源程序文件更加的模块化。

注意
在是使用 auto、static 或者 register 时,都是在定义变量时使用,不能单独给已经定义的变量使用

尾巴

这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。


-------------The End-------------
欢迎请我喝咖啡哦~!