开发者学堂课程【你的第一门 C 语言课:局部变量和全局变量】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/444/detail/5482
局部变量和全局变量
目录
一、局部变量
二、全局变量
一、局部变量
不同函数的变量无法相互访问:
void func(int a)
{
int b, c;
……
for (int i = 0; i < 10; i++)
{
……
}
}
int main()
{
int m, n;
……
return 0;
}
func 函数中定义了一个参数两个变量:a、b、c,还有一个 i,这4个变量在 main函数中是无法访问的;
同样的道理,在 main 函数中定义的 m、n 在 func 函数中也是无法访问到的,并不是说 main 是主函数就有特权可以访问的到,在 C 语言里函数的级别是一样的。
另外可以发现在 func 函数里有一个复合语句:由 for 语句构成的复合语句,在 for语句第一个表达式这里定义了一个变量 i,要注意在复合语句这一块 for 语句以及下面大括号括起来的这个语句块构成的复合语句,那么在这里的变量i作用范围就仅仅只限于这个复合语句里边,出了外边就访问不了了。
举个例子:
输入vi test1.c回车进入编译器:
#include
int main( )
{
int i = 520;
printf("before, i = %d\n", i);
for (int = 0;
i
< 10; i++)
{
printf("%d\n",i) ;
}
printf("after, i = d\n", i);
return 0 ;
}
输入g
cc -std=c99 test1.c && ./a.out
回车得出结果:
before
, i = 520
0
1
2
3
4
5
6
7
8
9
a
fter, i =520
可以发现在 for 中重复去定义一个同名的变量编译器并没有报错,因为在同一个函数里边是没办法同时定义两个相同名字的变量的,这会发生冲突,但是编译器竟然没有报错,这是因为他们的作用范围不同,所以不会互相发生冲突。
这里值得一提的是 for 语句因为定义了同名的变量 i,所以它屏蔽了外边的 i,内部的屏蔽了外部的,那么在这内部打印出的i必然是指里边的,而在外部的依然还是外部的。
不仅是打印,其他的访问、修改,改动的都是里边的这个i,因为同名所以把外面的屏蔽了。
二、全局变量
全局变量
- 在函数里边定义的,叫做局部变量;在函数外边定义的,叫做外部变量,也叫全
局变量。
- 有时候,可能需要在多个函数中使用共同的一个变量,那么就会用到全局变
量。因为全局变量可以被本程序中其他函数所共用。
如果每一名犯人都是一个函数,要统计小郭到底被抱了多少次,那么就在函数外部定义一个全局变量来统计。
输入vi test2.c回车进入编译器:
#include
void a();
void b();
void c();
int count=0;
void a()
{
count++ ;
}
void b()
{
count++ ;
}
void c()
{
count++ ;
}
int main( )
{
a();
b();
c();
b();
printf("小郭今天被抱了%d次! \n", count);
r
eturn 0;
}
输入g
cc -std=c99 test2.c && ./a.out
回车得出结果:
小郭今天被抱了4次!
因为 count 这个变量的定义在所有的函数的外部,所以它是全局变量,它的作用范围是整个程序,无论 main 函数也好 ABC 函数也罢,都可以对它进行访问和修改。所以这里初始化为零,之后count++,+1,又+1,又+1,因为这里调用了4次,a一次,b 一次,c 一次,b 觉得很舒服又来了一次,所以小郭被抱了4次。
- 如果不对全局变量进行初始化,那么它会自动初始化为0。
- 如果在函数的内部存在一个与全局变量同名的局部变量,编译器并不会报错,
而是再函数中屏蔽全局变量(也就是说在这个函数中,全局变量不起作用)。
例子:
输入vi test3.c回车进入编译器:
#include
void func();
int
a,b=520;
void func()
{
int b;
a= 880;
b=
120;
printf("In func, a = %d,
b
=%d\n", a, b);
}
int main( )
{
printf("In main, a = %d, b = %d\n", a, b) ;
func();
printf("In main, a = %d, b = %d\n", a, b);
return 0 ;
}
这个实验就是要看一下对这个局部变量 b 会对它进行屏蔽,所以说在这里的修改应该不会影响到这个全局变量 b 的值,这是第一个实验的目标。第二个实验是要证明说这个 a 如果没有对它进行初始化,它会自动初始化为0。
程序一执行就进入 main 函数,首先打印它,a 没有对它进行初始化,打印的是0还有520,然后进入 func 函数,定义了一个局部变量 b 和全局变量是同名的,所以在func 里边这个 b 把全局变量b屏蔽了,所以b=120,所以这里打印的应该是a=880。
输入gcc -std=c99 test3.c && ./a.out回车得出结果:
I
n main, a = 0, b = 520
In func, a =880, b =120
I
n main, a = 880, b =520
如果一个全局变量在函数的定义之后才被定义,会有什么事情发生呢,不妨试试看:
输入vi test4.c回车进入编译器:
#include
void func( );
void func()
{
count++;
}
int count =0;
i
nt main()
{
func( ) ;
printf(“%d\n”,count);
return 0;
}
输入g
cc -std=c99 test4.c && ./a.out
回车得出结果:
test4.c: In function ' func':
test4.c:7: error: 'count'undeclared(first use in this function)
test4.c:7: error:(Each undeclared identifier is reported only once
test4.c:7: error: for_each function it appears in. )
可以看见报错,需要用extern关键字:
#include
void func( );
void func()
{
extern
count;
count++;
}
int count =0;
i
nt main()
{
func( ) ;
printf(“%d\n”,count);
return 0;
}
输入gcc -std=c99 test4.c && ./a.out回车得出结果:
1
这个技巧可以用在多个源文件之间。
不要大量的使用全局变量
- 使用全局变量会使程序占用更多的内存,因为全局变量从被定义时候开始,直
到程序退出才被释放。
- 污染命名空间,虽然局部变量会屏蔽全局变量,但这样一来也会降低程序的可
读性,人们往往很难一下子判断出每个变量的含义和作用范围。
- 提高了程序的耦合性,牵一发而动全身,时间久了,代码长了,都不知道全局
变量被哪些函数修改过。