1.局部变量
(1)局部变量也称为内部变量,他是在函数体内作定义说明的,其作用域仅限于函数内部,离开该函数后再使用这种变量是非法的。
如:func ()
{ int x; 局部变量x的作用域 在函数体内
//......
}
(2)一个函数可以为局部变量定义任何名字,而不用担心其他函数使用过同样的名字。
void main()
{ int n; //等价于auto intn;
//...
}
void func()
{ int n;
//...
}
代码中两个函数都包含一个变量定义语句。在函数内定义的变量局部于该函数。main()函数中有一个变量n,func()函数中也有一个变量n,但它们是两个不同位置的变量。
一个函数可以为局部变量定义任何名字,而不用担心其他函数使用过同样的名字,这个特点和局部变量的存在性使C++适合于由多个程序员共同参与的编程项目,项目管理员为程序员指定编写函数的任务,并为程序提供参数和期望的返回值。然后,程序员着手编写函数,而不用了解程序的其他部分和项目中其他程序员所使用的变量名。
(3)局部变量没有默认初始化。如果局部变量不被显式初始化,那么,其内容是不可预料的。所以局部变量必须要初始化。
#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
在func1()中,定义了局部变量n,并给其初始化为12345。在func2()中,定义了局部变量m,没有初始化。 可是在将该变量值返回后,在主函数中输出该值,却发现为12345,恰好就是funcl()函数中初始化的值。这说明,func2()中,没有显式初始化的局部变量m,C++也未给其默认初始化,其值保留为原内存位置的值。这是函数的调节机制造成的。
(4)局部变量从存储方式上可分为动态(auto)存储类型和静态(static)存储类型。
动态存储类型的局部变量都是动态的分配存储空间,数据存储在动态存储区(栈)中。函数调用结束后自动释放,生存期是在声明该变量的函数执行过程。
静态存储类型的局部变量则是静态的分配存储空间,数据存储在静态存储区中。在程序整个运行期间都不释放,生存期贯穿于程序运行的整个过程。但是其他函数不能调用静态局部变量,当再次进入该函数时,将保存上次的结果。
函数中的局部变量,如不专门声明为static存储类别,默认都是动态地分配存储空间的,我们在平时的声明变量的过程中auto都是默认省略的。
2.全局变量
(1)全局变量也称为外部变量,是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。在程序执行过程中它们占据固定的存储单元,而不动态地进行分配和释放。如果外部变量不在文件的开头定义,其有效作用域只限于定义处到文件终。如果一个函数修改了某个全局变量,则所有其他的函数都会看到修改后的这个全局变量
(2)全局变量有默认的初始化。
对于全局变量,如果在定义的时候不做初始化,则系统将自动为起赋值,数值型为0;字符型为空'/0'。
全局变量的弊端,增加内存开销,降低函数的通用性
(3)对全局变量的引用。
定义全局变量时理想的位置是在文件的开头,当这些函数以及同一个程序中的其他源程序文件中的某些函数需要使用该全局变量时,在函数内部对该变量使用extern 加以说明 说明他是外部的 。
如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。其有效作用域就被拓展到从这个文件extern声明处到文件结束。
(4)对全局变量的声明和对全局变量的定义的区别。
对外部变量的说明,只是声明该变量是在外部定义过的一个全局变量在这里引用 ;而对全局变量的定义则是要对其分配存储单元。一个全局变量只能定义一次,可是却可以多次引用。
(5)static(静态)全局变量与普通的全局变量的区别。
非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
(6)局部变量能和全局变量重名,但是局部变量会屏蔽全局变量。在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。这对extern声明的全局变量也一样。
顺便梳理一下:
3.程序的内存区域
并不是所有的变量时时刻刻都是可知的。一些变量在整个程序中都是可见的,它们称为全局变量;一些变量只能在一个函数中可知,称为局部变量。要了解变量的这些属性,应先弄清程序在内存中的分布区域。
一个程序将操作系统分配给其运行的内存块分为4个区域:
(1)代码区,存放程序的代码,-----程序中的各个函数代码块。
(2)全局数据区,存放程序的全局数据和静态数据。----全局变量、静态局部变量
(3)堆区,存放程序的动态数据。-----动态申请的数据,如new出来的数据
(4)栈区,存放程序的局部数据,即各个函数中的数据。------局部变量
即:一般全局变量存放在数据区,局部变量存放在栈区,动态变量存放在堆区,函数代码放在代码区。
4.静态变量的特点:
(1)一次存储:静态局部变量只被初始化一次,下一次初始化根据上一次的结果值,有点类似于c++中类的静态成员变量,即无论该类型生成多少个实例对象,所有的对象共用一个静态变量,到这里就是无论这个函数调用多少次,该静态变量只初始化一次,并没有因为超出其生存期而被销毁,只是外部不可见而已,用个例子说明之:
void fun1( int v ) { static int value = v; } int main( int arc, char *args[ ]) { fun1( 50 ); fun1( 100 ); } |
执行的结果是:value :50 value : 50
说明在第二次调用fun1( )时的初始化value的采用的是上一次value的值,value在静态区的存储空间并没有因为fun1( )的结束而被释放,即体现了一次存储;
(2)作用域限定:
静态修饰的作用域限定,能同时体现在函数与变量上;
a)对于函数而言,任何用static修饰的函数,其作用域仅为当前源文件,而对外部来说这个函数是不可见的,即只有和其在同一源文件中的函数才能调用这个静态函数;反过来说,如果一个函数仅仅被同一源文件中的其他函数调用,那么这个函数应该声明为静态的,这样做的好处在于:可以一定程度上的解决不同源文件之间函数的命名冲突问题;
b)对于变量而言,static修饰的全局变量,只在当前源文件中有效,对外部不可见,外部文件不能够引用;静态全局变量的意义就是不让“外部”引用,是单个源文件里的全局变量,即是编译阶段的全局变量,而不是连接阶段的全局变量。
通过上面的分析,我们不难得出以下结论:
1、静态函数与普通函数的区别在于:静态函数不可以被同一源文件以外的函数调用。
2、静态局部变量与普通局部变量的区别在于:静态局部变量只初始化一次,下一次初始化实际上是依然是上一次的变量;
3、静态全局变量与普通全局变量的区别在于:静态全局变量的作用域仅限于所在的源文件。