C-作用域

1.9k 词

作用域

在先前的教程中,已经提到了全局变量这一概念。全局变量就是作用域之一。作用域决定了变量可访问性。在超出作用域的位置不能访问对应变量。

C 中,有三种地方可以声明变量:

  • 在所有函数之外的全局变量

  • 在函数或代码块内部的局部变量

  • 在函数声明中的形式参数

全局变量

全局变量顾名思义,在程序中的任意地方均可访问。全局变量声明在所有函数之外。

在所有函数之外也可以声明全局常量。

1
2
3
4
5
6
7
#include <stdio.h>

int global_var = 10086;//全局变量

int main(){
printf("Hello,World\n");
}

很多时候全局变量只是为了在当前文件中传递信息或者别的用途,不想其他文件可以访问到这个变量,这时候可以使用 static 存储类。 static 的全局变量的作用域会被限制在当前文件,即使在其他文件内使用 extern 也访问不到。

局部变量

局部变量是声明在函数或代码块内的变量。其作用域局限在代码块内,只在代码块内可以使用,代码块外不可访问。

如果局部变量与全局变量重名,则优先使用局部变量。如果存在作用域嵌套,内层变量与外层同名,则在内存作用域优先使用内层变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int homo = 0;

int main(){
int homo = 810;//与全局变量同名的局部变量,在作用域内优先使用局部变量
int local_var = 10086;//局部变量
{
int local_var_inner = 514;//也是局部变量,作用域为所在的代码块
int local_var = 114;//与外层作用域的局部变量同名,在本作用域优先使用此变量。
printf("Inner: %d\n",local_var);

}
if (homo > 514){
int homo = 1919810;//与外层作用域的局部变量同名,在本作用域优先使用此变量。
printf("%d\n",homo);
}
printf("Hello,World\n");
}

局部变量会被分配在栈上存储,会随着函数运行结束栈空间回收被一起回收。如果不想局部变量被回收可以使用 static 存储类。 static 变量会被分配在静态存储区上,不会随着栈回收而被回收。

形式参数

函数的参数即形式参数,作用域为函数体内部,如果与全局变量同名会优先使用参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int sum = 0;

void print_sum(int sum);

int main(){
print_sum(114514);
}

void print_sum(int sum){
printf("Sum = %d\n",sum);
}

//输出 Sum = 114514

作用域相关的变量初始化

在声明变量时如果没有手动初始化,全局变量和静态变量会被编译器自动初始化为 0值 (数字类型为0,指针类型为NULL),局部变量则是随机值。

  1. 静态变量与全局变量

程序内存区域中有两个区段: databss 区段,用来存放全局变量和静态变量,其空间在程序运行结束后自动释放。其中 data 区段用于存放已初始化的全局变量和静态变量; bss 区段用于存放为初始化的全局变量和静态变量,并在程序运行前被自动清零。所以未初始化的全局变量和静态变量在程序执行之前已经为0。

  1. 局部变量
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int g;

int main(){
static int s;
int l;
printf("Global: %d\n",g);
printf("Static: %d\n",s);
printf("Local : %d\n",l);
}
//输出 Sum = 114514

多次尝试时会发现,未初始化的局部变量的值似乎一直都是0。这是因为未初始化的局部变量会被直接指派到未经任何处理的原生栈空间上,其内容为内存内部的随机垃圾值。然而内存很大,可能大部分空间都为默认值0,所以会产生这种情况。但是正因为是垃圾值,其内容完全不可控,所以变量声明后一定要初始化。

  1. 形式参数

形参的值由传入值决定,在给函数传参时参数不够或类型不对会导致编译器报错,如果通过函数指针强行传入,缺少的参数会被初始化为随机值。

写在最后

作用域控制着变量的使用范围,管理好作用域,保证变量之间不会互相干扰。

留言