并不是所有的变量时时刻刻都是可知的。一些变量在整个程序中都是可见的,它们称为全局变量。一些变量只能在一个函数中可知,称为局部变量。要了解变量的这些属性,应先弄清程序在内存中的分布区域,见图5-2。
图5-2 程序在内存中的区域
一个程序将操作系统分配给其运行的内存块分为4个区域:
(1)代码区,存放程序的代码,即程序中的各个函数代码块。
(2)全局数据区,存放程序的全局数据和静态数据。
(3)堆区,存放程序的动态数据。
(4)栈区,存放程序的局部数据,即各个函数中的数据。
2.全局变量
在函数外边访问的变量被认为是全局变量,并在程序的每个函数中是可见的。全局变量存放在内存的全局数据区。全局变量由编译器建立,并且初始化为0,在定义全局变量时,进行专门初始化的除外。
例如,下面的代码定义并使用了全局变量。:
int n=5; //全局变量
void main()
{
int m=n;
//...
}
void func()
{
int s;
n=s;
//...
}
n在任何函数的外部定义。 n被初始化为5, 如果n不在定义时初始化,则C++将其初始化为0。 main()函数使用变量n1,函数func()修改变量n。两个函数都访问了同一个内存区域。这样定义的全局变量。在所有函数中都可见。如果一个函数修改了n,则所有其他的函数都会看到修改后的变量。
全局变量在主函数main()运行之前就开始存在了。所以主函数中可以访问n变量。 全局变量通常在程序顶部定义。全局变量一旦定义后就在程序的任何地方可知。可以在程序中间的任何地方定义全局变量,但要在任何函数之外。全局变量定义之前的所有函数定义,不会知道该变量。例如:
void main()
{
int m=n; //error:n无定义
//...
}
int n;//全局变量
void func()
{
int s=3;
n=s;
//...
}
该代码中的全局变量n不能被主函数main()访问。 编译该代码,将会引起main()中的m初始化语句报告一个“n无定义”的错误。
3.局部变量
在函数内部定义的变量仅在该函数内是可见的。另外,局部变量的类型修饰是auto,表示该变量在栈中分配空间,但习惯上都省略auto。例如:
void main()
{
int n; //等价于auto intn;
//...
}
void func()
{
int n;
//...
}
代码中两个函数都包含一个变量定义语句。在函数内定义的变量局部于该函数。main()函数中有一个变量n,func()函数中也有一个变量n,但它们是两个不同位置的变量。
一个函数可以为局部变量定义任何名字,而不用担心其他函数使用过同样的名字。 这个特点和局部变量的存在性使C++适合于由多个程序员共同参与的编程项目。项目管理员为程序员指定编写函数的任务,并为程序提供参数和期望的返回值。然后,程序员着手编写函数,而不用了解程序的其他部分和项目中其他程序员所使用的变量名。
函数中的局部变量存放在栈区。在函数开始运行时,局部变量在栈区被分配空间,函数退出时,局部变量随之消失。
局部变量没有初始化。如果局部变量不被显式初始化,那么,其内容是不可预料的。例如:
//*********************
//** ch5_1.cpp **
//*********************
#include <iostream.h>
int func1();
int func2();
void main()
{
func1();
cout <<func2() <<endl;
}
int func1()
{
int n=12345;
return n;
}
int func2()
{
int m;
return m; //warning:possible use of 'm' before definition
}
运行结果为:
12345
主函数main()先后调用了函数func1()和func2(),它们都是无参并返回整数的函数。
在func1()中,定义了局部变量n,并给其初始化为12345。在func2()中,定义了局部变量m,没有初始化。 可是在将该变量值返回后,在主函数中输出该值,却发现为12345, 恰好就是funcl()函数中初始化的值。这说明,func2()中,没有显式初始化的局部变量m,C++也未给其默认初始化,其值保留为原内存位置的值。那么,原内存位置为什么恰巧是存放值12345的位置呢?请见下节“函数调用机制”。
要点:
1、全局变量:
(1)在函数外定义
(2)在全局可见
(3)一般在程序顶部定义
(4)存放在内存的全局数据区
(5)如在定义时未初始化,则其值为0
(6)如果一个函数修改了n,则所有其他的函数都会看到修改后的变量
2、局部变量:
(1)在函数内部定义
(2)仅在该函数内可见
(3)存放于栈区,函数退出时,局部变量随之消失
(4)不同函数可使用同一个变量名
(5)如果局部变量不被显式初始化,其内容则不可预料