全局变量和局部变量及作用域(C)

本文详细解释了C语言中局部变量和全局变量的概念,讨论了它们的作用域、命名规则以及在函数调用中的行为,强调了变量在不同作用域中的隔离性。
摘要由CSDN通过智能技术生成

目录

局部变量:

全局变量:

在函数内部定义的变量:

在所有函数外部定义的变量: 


局部变量:

定义在函数内部的变量称为局部变量,它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。例如:

int f1(int a){
    int b,c;  //a,b,c仅在函数f1()内有效
    return a+b+c;
}
int main(){
    int m,n;  //m,n仅在函数main()内有效
    return 0;
}

几点说明:
1) 在 main 函数中定义的变量也是局部变量,只能在 main 函数中使用;同时,main 函数中也不能使用其它函数中定义的变量。main 函数也是一个函数,与其它函数地位平等。

2) 形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。

3) 可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互不干扰,也不会发生混淆。

4) 在语句块中也可定义变量,它的作用域只限于当前语句块。

全局变量:

在所有函数外部定义的变量称为全局变量,它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。例如:

int a, b;  //全局变量
void func1(){
    //TODO:
}
float x,y;  //全局变量
int func2(){
    //TODO:
}
int main(){
    //TODO:
    return 0;
}

a、b、x、y 都是在函数外部定义的全局变量。C语言代码是从前往后依次执行的,由于 x、y 定义在函数 func1() 之后,所以在 func1() 内无效;而 a、b 定义在源程序的开头,所以在 func1()、func2() 和 main() 内都有效。

#include <stdio.h>
int n = 10;  //全局变量
void func1() {
    int n = 20;  //局部变量
    printf("函数1 %d\n", n);
}
void func2(int n) {
    printf("函数2 %d\n", n);
}
void func3() {
    printf("函数3 %d\n", n);
}
int main() {
    int n = 30;  //局部变量
    func1();
    func2(n);
    func3();
    //代码块由{}包围
    {
        int n = 40;  //局部变量
        printf("代码块中的n %d\n", n);
    }
    printf("主函数中的n %d\n", n);
    return 0;
}

运行结果: 

1) 对于 func1(),输出结果为 20,显然使用的是函数内部的 n,而不是外部的 n;func2() 也是相同的情况。

当全局变量和局部变量同名时,在局部范围内全局变量被“屏蔽”,不再起作用。或者说,变量的使用遵循就近原则,如果在当前作用域中存在同名变量,就不会向更大的作用域中去寻找变量。

2) func3() 输出 10,使用的是全局变量,因为在 func3() 函数中不存在局部变量 n,所以编译器只能到函数外部,也就是全局作用域中去寻找变量 n。

3) 由{ }包围的代码块也拥有独立的作用域,printf() 使用它自己内部的变量 n,输出 40。

4) C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量。对于 main() 函数,即使代码块中的 n 离输出语句更近,但它仍然会使用 main() 函数开头定义的 n,所以输出结果是 30。

在函数内部定义的变量:

在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了,我们将这样的变量称为局部变量(Local Variable)。函数的形参也是局部变量,也只能在函数内部使用。

#include <stdio.h>
int sum(int m, int n) {
    int i, sum = 0;
    //m、n、i、sum 都是局部变量,只能在 sum() 内部使用
    for (i = m; i <= n; i++) {
        sum += i;
    }
    return sum;
}
int main() {
    int begin = 5, end = 86;
    int result = sum(begin, end);
    //begin、end、result 也都是局部变量,只能在 main() 内部使用
    printf("%d 到 %d 的总和是 %d\n", begin, end, result);
    return 0;
}

 运行结果:

m、n、i、sum 是局部变量,只能在 sum() 内部使用;begin、end、result 也是局部变量,只能在 main() 内部使用。

对局部变量的两点说明:

  • main() 也是一个函数,在 main() 内部定义的变量也是局部变量,只能在 main() 函数内部使用。
  • 形参也是局部变量,将实参传递给形参的过程,就是用实参给局部变量赋值的过程,它和a=b; sum=m+n;这样的赋值没有什么区别。

在所有函数外部定义的变量: 

C语言允许在所有函数的外部定义变量,这样的变量称为全局变量。

全局变量的默认作用域是整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件)。如果给全局变量加上 static 关键字,它的作用域就变成了当前文件,在其它文件中就无效了。我们目前编写的代码都是在一个源文件中,所以暂时不用考虑 static 关键字。

定义一个函数,根据长方体的长宽高求它的体积以及三个面的面积。

#include <stdio.h>
//定义三个全局变量,分别表示三个面的面积
int s1 = 0, s2 = 0, s3 = 0;
int vs(int length, int width, int height){
    int v;  //体积
    v = length * width * height;
    s1 = length * width;
    s2 = width * height;
    s3 = length * height;
    return v;
}
int main(){
    int v = 0;
    v = vs(15, 20, 30);
    printf("v=%d, s1=%d, s2=%d, s3=%d\n", v, s1, s2, s3);
    v = vs(5, 17, 8);
    printf("v=%d, s1=%d, s2=%d, s3=%d\n", v, s1, s2, s3);
    return 0;
}

运行结果:

根据题意,我们希望借助一个函数得到四份数据:体积 v 以及三个面的面积 s1、s2、s3。遗憾的是,C语言中的函数只能有一个返回值,我们只能将其中的一份数据(也就是体积 v)放到返回值中,其它三份数据(也就是面积 s1、s2、s3)只能保存到全局变量中。

C语言代码从前往后依次执行,变量在使用之前必须定义或者声明,全局变量 s1、s2、s3 定义在程序开头,所以在 vs() 和 main() 中都有效。

在 vs() 中将求得的面积放到 s1、s2、s3 中,在 main() 中能够顺利取得它们的值,这说明:在一个函数内部修改全局变量的值会影响其它函数,全局变量的值在函数内部被修改后并不会自动恢复,它会一直保留该值,直到下次被修改。

全局变量也是变量,变量只能保存一份数据,一旦数据被修改了,原来的数据就被冲刷掉了,再也无法恢复了,所以不管是全局变量还是局部变量,一旦它的值被修改,这种影响都会一直持续下去,直到再次被修改。

关于变量的命名:

每一段可运行的C语言代码都包含了多个作用域,即使最简单的C语言代码也是如此。

int main(){
    return 0;
}

这就是最简单的、可运行的C语言代码,它包含了两个作用域,一个是 main() 函数内部的局部作用域,一个是 main() 函数外部的全局作用域。

C语言规定,在同一个作用域中不能出现两个名字相同的变量,否则会产生命名冲突;但是在不同的作用域中,允许出现名字相同的变量,它们的作用范围不同,彼此之间不会产生冲突。这句话有两层含义:

  • 不同函数内部可以出现同名的变量,不同函数是不同的局部作用域;
  • 函数内部和外部可以出现同名的变量,函数内部是局部作用域,函数外部是全局作用域。
#include <stdio.h>
void func_a(){
    int n = 100;
    printf("func_a: n = %d\n", n);
    n = 86;
    printf("func_a: n = %d\n", n);
}
void func_b(){
    int n = 29;
    printf("func_b: n = %d\n", n);
    func_a(); //调用func_a()
    printf("func_b: n = %d\n", n);
}
int main(){
    func_b();
    return 0;
}

 运行结果:

func_a() 和 func_b() 内部都定义了一个变量 n,在 func_b() 中,n 的初始值是 29,调用 func_a() 后,n 值还是 29,这说明 func_b() 内部的 n 并没有影响 func_a() 内部的 n。

2) 函数内部的局部变量和函数外部的全局变量同名时,在当前函数这个局部作用域中,全局变量会被“屏蔽”,不再起作用。也就是说,在函数内部使用的是局部变量,而不是全局变量。

变量的使用遵循就近原则,如果在当前的局部作用域中找到了同名变量,就不会再去更大的全局作用域中查找。另外,只能从小的作用域向大的作用域中去寻找变量。
 

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值