先说几个概念:
1.从变量的生存期来分,可以分为 静态存储方式 和
动态存储方式
静态存储方式:程序运行期间由系统分配固定的存储空间的方式(全局变量)
动态存储方式:程序运行期间根据需要动态的分配存储空间的方式(1.函数形参,2自动变量,3函数调用时的现场保护盒返回地址)
2.数据存储类别包含四种:auto(自动), static (静态),register(寄存器),
extern (外部)
auto: 关键字auto可以省略,auto不写隐含确定为自动存储类别,属于动态存储方式
static: 有时候希望i函数的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量已经有值(上一次函数调用结束时的值)
例子:
#include "stdafx.h" #include <iostream> using namespace std; int fun(int a) { int b=0; static int c=3; b++; c++; return a+b+c; } int _tmain(int argc, _TCHAR* argv[]) { int a=100; for (int i = 0; i < 3; i++) { cout<<fun(a)<<endl; } return 0; }
输出结果:
a的值不变
b每次调用时初值为0,调用后为1
c调用时初值分别为3,调用后位4
------ 4,-------------5
------ 5,-------------6
说明:
1.静态局部变量属于静态存储类别,在静态存储区内分配存储单元
2.对于静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值,以后每次调用函数时不再重现赋初值而只是保留上次函数调用结束时的值。(自动变量赋初值,不是在编译时,而是在函数调用时进行,每次重现调用都重新赋予初值)
3.如果不赋予初值,对于静态局部变量来说,编译时自动赋值0(int型)或空字符(char型);而对于自动变量来说,不赋初值则它是一个不确定的值。
4.虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。
register :如果一些变量使用频繁,可以用关键字register作声明(由于对寄存器的存取速度远高于对内次的存取速度,这样做可以提高执行效率)
说明:
1.只有局部自动变量和形参可以作为寄存器变量,其它如全局变量不行
2.一个计算机中的寄存器数目是有限的,不能定义任意多个寄存器变量。不同的系统允许使用的寄存器个数是不同的,对register变量的处理方法也是不同的,有的系统对register变量当作自动变量处理,分配存储单元,并不真正把它们存放在寄存器中,有的系统只允许将int,char和指针变量定义为寄存器变量。
3.局部变量不能定义为寄存器变量,不能将变量既放在静态存储区,又放到寄存器中,二者只能居其一。对于一个变量只能声明为一种存储类别
4.当今优化编译系统能够识别使用频繁的变量,从而自动将这些变量放在寄存器中,不需要程序设计者指定。因此,实际上用register声明变量是不必要的。
extern :
外部变量:外部变量是在函数的外部定义的变量,它的作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序中的各个函数所引用。编译时将外部变量分配在静态存储区。
用extern来声明外部区域,扩展外部变量的作用域。
1.在一个文件内声明外部变量
如果外部变量不在定义的开头定义,其有效的作用范围只限定于定义处到文件结束。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量做外部变量声明,表示该变量是一个已经定义的外部变量,有了此声明,就可以从声明处起,合法地使用该外部变量。
// CTestProject.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { extern int A,B; cout<<"A:"<<A<<endl; cout<<"B:"<<B<<endl; return 0; } int A=5,B=10;
如果没有extern int A,B这句,则会报卫生棉的标识符A,B
当然更好的做法是:外部变量的定义放在引用它的所有函数之前,可以避免函数中添加一个extern关键字
#include "stdafx.h" #include <iostream> using namespace std; int A=5,B=10; int _tmain(int argc, _TCHAR* argv[]) { //extern int A,B; cout<<"A:"<<A<<endl; cout<<"B:"<<B<<endl; return 0; }
2.在多个文件的程序中声明外部变量
如果程序有多个源文件,在一个文件想引用另一个文件中已定义的外部变量,可以使用extern 扩展作用域。
如:a.c文件 有个变量A,b.c想引用变量A,只需要在文件开头处extern A即可(不能分别在a.c b.c文件中各自定义一个变量A,否则在程序连接时会出现重复定义的错误),在编译和连接时,系统会由此知道A是一个已经在别处定义的外部变量,并将在另外一个文件中定义的外部变量的作用域扩展到本文件,在本文件中可以合法的引用外部变量A
extern既可以扩展外部变量在本文件的作用域,又可以扩展外部变量的作用域从一个文件到另外一个文件,系统的处理规则是:
1,先在本文件中招外部变量的定义,如果找到,就在本文件中扩展作用域;
2,如果找不到,就在连接时从其他文件中找外部变量的定义,如果找到,就将作用域扩展到本文件;
3,如果未找到,就按出错处理
3.静态外部变量(用static 声明外部的变量)
如果在程序设计中希望某些外部变量只限于被本文件引用,而不能被其他文件引用,则可以使用static声明
如:a.c
static int A
void main()
{
...
}
b.c
extern int A;
void fun()
{
....
}
b.c文件中无法使用a.c中的全局变量A