不知道大家如何,反正我最开始接触 C 语言编程时,最让我觉得神奇的就是变量的使用了,“a=1”之后又可以“a=0”。事实上,不仅仅是 C 语言,无论哪一门编程语言,变量都是基石,离开变量啥都做不了。
变量和赋值
请看下面的例子,很容易明白,变量只是一个容器,真正具有使用意义的是它装载的数据。C 语言中的“=”可以改变变量装载的数值,程序员常常称这一过程为“赋值”。
#include <stdio.h>
int main()
{
int a = 3;
printf("the variable is %d\n", a);
return 0;
}
// 程序输出 the variable is 3
变量就好像鞋柜一样,它可以装很多不同的鞋子。里面装了布鞋,你可以从中拿出布鞋穿。里面装了皮鞋,你可以从中拿出皮鞋穿。“=”就相当于往鞋柜放鞋子。
局部变量和全局变量
局部变量
我们把函数中定义的变量称为局部变量,因此函数的形参也属于局部变量,这里的局部变量有两个含义:
1、某个函数中定义的变量,不能被另一个函数使用。请看下面的例子,我们在 print_int 函数中定义了变量 b,它是不能在 print_again 里使用的。所以下面这样写,就会报语法错误。关于语法错误可参考我之前的文章。《》
void print_int(int a)
{
int b = 3;
printf("%d, %d\n", a, b);
}
void print_again()
{
printf("%d\n", b);
}
2、每次调用函数时,局部变量都表示不同的存储空间。局部变量实在每次函数调用时,才分配的存储空间,被调用函数返回时,这部分存储空间就被释放了。例如上面这个程序,调用 print_int(2) 时,分配给 a 的存储空间里存放的是 2。下一次调用 print_int(3) 时,分配给 a 的存储空间存放的就是 3 了。
全局变量
与局部变量相对应的就是全局变量了,全局变量在整个程序的所有函数中,都能访问。我们将上面的代码做一点点修改,即将 b 变为全局变量,请看如下代码:
int b = 1;
void print_int(int a)
{
b = 3;
printf("%d, %d\n", a, b);
}
void print_again()
{
printf("%d\n", b);
}
这时再编译,就不会出现语法错误了。那执行 print_again 函数,会输出多少呢?答案是取决于函数的执行顺序。b 被初始化为 1,如果之前没有调用 print_int ,那调用 print_again 打印出的 b 的值就是 1。如果先调用 print_int,再调用 print_again,那打印出的就是 3。因为在 print_int 中,b 被修改为 3 了。
源代码的书写顺序并不代表函数的执行顺序。
可以看出,全局变量使用起来虽然方便,但是一定要慎用。因为任意位置都可能会修改它,而对于大型规模的开发,理清调用顺序也是一件体力活,出现了 bug 可能就是因为某个不起眼的地方对全局变量的读写造成的。
全局变量的初始化只能用常量表达式初始化,例如,对 pi 全局变量初始化时合法的:
double pi = 3.14 + 0.0016;
但这样初始化是不合法的:
double pi = acos(-1.0);
下面这样的初始化也是不合法的:
int minute = 360;
int hour = minute / 60;
全局变量和局部变量同名
则第一次调用print_time打印的是全局变量的值,第二次直接调用printf打印的则是main函数的局部变量的值。在C语言中,每个标识符都有特定的作用域(Scope),全局变量是定义在所有函数体之外的标识符,它的作用域从定义的位置开始直到源文件结束,而main函数局部变量的作用域仅限于main函数之中。如上图所示,设想整个源文件是一张大纸,也就是全局变量的作用域,而main函数是贴在这张大纸上的一张小纸,也就是main函数局部变量的作用域。在小纸上用到标识符hour和minute时应该参考小纸上的定义,因为大纸(全局变量的作用域)被盖住了,如果在小纸上用到某个标识符却没有找到它的定义,那么再去翻看下面的大纸,例如上图中的变量x。