C++之——变量的存储类别及static、register、extern用法

版权声明:转载请注明出处 https://blog.csdn.net/qq_35294564/article/details/82627474

一、变量属性

1.作用域:从空间角度来分析的,分为全局变量和局部变量。

2.存储期:也称生命期,指变量在内存中的存在时期,是从变量在内存中的存在时间来分析的,存储期可分为静态存储期和动态存储期,这是由变量的动态存储方式和静态存储方式决定的。

        数据分别存放在静态存储区和动态存储区中,全局变量全部存放在静态存储区中,在程序开始执行时给全局变量分配存储单元,程序执行完毕就释放这些空间,在程序执行过程中,它们占据固定的存储单元,而不是动态的进行分配和释放。

        在动态存储区中存放以下数据:①函数形参 ②函数中的自动变量(未加static声明的局部变量)③函数调用时的现场保护和返回地址等。

3.存储类别:① 自动的(auto)② 静态的(static)③ 存储器的(register)④ 外部的(extern)

二、自动变量(auto)自动确认变量类型、节约存储空间

        函数中的局部变量,如果不用static加以声明,编译系统对它们是进行动态的分配存储空间的,调用或执行时分配,调用、执行完毕后释放。

三、静态变量(static)保留上一次运算结果

         有时希望函数中的局部变量再调用结束后不消失而且保存原值,即其占用的存储单元不释放,在下一次函数调用时,该变量保留上一次函数调用结束时的值,这时就应指定为局部静态变量。

         如下利用fac()函数求阶乘,利用局部变量f保存每次与下一个数相乘后的结果:

#include<iostream>
using namespace std;
int fac(int);
int main() {
	int i;
	for (i = 1; i <= 10; i++) {
		cout << i << "! = " << fac(i) << endl;
	}
	return 0;
}

int fac(int n) {
	static int f = 1;
	f *= n;
	return f;
}

运行结果:

对静态局部变量的说明:

  1. 静态局部变量在静态存储区内分配存储单元,在程序整个运行期间都不释放
  2. 为局部变量赋初值是在编译时进行赋值的,即只赋初值一次,以后每次调用都不再重新赋值,而只是保留上次函数运行结束时的值。而为自动变量赋初值不是在编译的时候进行的,而是在函数调用时进行的,每调用一次就重新给一次初值,相当于执行一次赋值语句。
  3. 如果在定义局部变量时不赋初值,那么对局部静态变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符型变量),而对自动变量来说,如果不赋初值,则它的值是一个不确定的值。
  4. 虽然说静态局部变量在函数调用后仍存在,但其他函数是不能引用他的,就是说在其他函数中它是不可见的。

四、寄存器变量(register)提高运行效率

          一般情况下,变量(包括静态和动态存储方式)的值是存放在内存中的,当程序中用到哪一个变量时,由控制器发出指令将内存中该变量的值送到CPU中的运算器,经过运算器的运算,如果需要存数,再从运算器将数据送到内存存放。

          如果有一些变量使用频繁(如在一个函数中执行10000次),则存取变量的值需要花费不少的时间,为提高执行效率,C++允许将局部变量的值放在CPU的寄存器中,需要用时直接从寄存器中取出数据参加运算,不必再到存储器中去存取。对寄存器的存取速度远远高于内存,因此可以提高执行效率。这种变量叫做寄存器变量,用register作声明。

#include<iostream>
using namespace std;
int fac(int);
int main() {
	int i;
	for (i = 1; i <= 10; i++) {
		cout << i << "! = " << fac(i) << endl;
	}
	return 0;
}

int fac(int n) {
	register int i,f = 1;
	for (i = 1; i <= n; i++) {
		f *= i;
	}
	return f;
}

结果同上。

五、用extern声明外部变量(以扩展全部变量的作用域)

          全局变量(外部变量)是在函数外部定义的,它的作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内全局变量可以为文件中各个函数所引用。编译时将全局变量分配在静态存储区。

      1、在一个文件内声明全局变量

             如果全局变量不在文件的开头定义,其有效作用域只限于定义处到文件终了。而如果在定义点之前函数想引用该全局变量,则应该在引用之前用关键字extern对该变量作外部变量声明,表示该变量是一个将在下面定义的全局变量,有了此声明,就可以从声明处起,合法的引用该全局变量,这种声明称为提前引用声明

#include<iostream>
using namespace std;
int max(int, int);
void main() {
	extern int a, b;
	cout << max(a, b) << endl;
}
int max(int x, int y) {
	int z;
	z = x > y ? x : y;
	return z;
}
int a = 15, b = -9;

      2、在多文件的程序中声明外部变量

            如果一个程序包含两个文件,两个文件中都要用到两个全局变量(外部变量)a、b,不能分别在两个文件中都定义一次外部变量a、b,否则在进行程序的连接时会出现“重复定义”。

            正确的做法是:在任一个文件中定义外部变量a、b,而在另一个文件中用extern对a、b做外部变量声明。

//main.cpp文件

#include <iostream>
//#include "another.cpp"         //不需要包含另一个.cpp文件,直接可以把两个源文件编译到一起
using namespace std;
int max(int, int);
void main() {
	extern int a, b;
	cout << max(a, b) << endl;
}
//another.cpp文件

int max(int x, int y) {
	int z;
	z = x > y ? x : y;
	return z;
}
int a = 15, b = -9;

即       extern int a, b;

 编译系统由此知道a、b是已经在别处定义的外部变量,它先在本文件中找有无全局变量a、b,如果有,则将其作用域扩展到本行开始,若本文件中无此外部变量,则在程序连接时从其他文件中找有无外部变量a、b,如果有,则把在另一个文件中定义的外部变量a、b的作用域扩展到本文件,在本文件中可以合法的引用该外部变量a、b。

  注:多文件公用的全局变量在一个文件中值可能会改变,从而影响另一个文件中的执行结果,慎重使用。

六、用static声明静态外部变量

           在another.cpp中定义了一个全局变量a,但用static声明,因此只能用于本文件,虽然在main.cpp文件中用了“extern int a;”,但main.cpp文件中仍无法使用another.cpp中的全局变量a。

          这种加上static声明,只能用于本文件的外部变量(全局变量)称为静态外部变量。

          在程序设计中,常有若干人完成各个模块,各个人可以独立的在其设计的文件中使用相同的全局变量名而互不相干。只需在每个文件的全局变量前加上static,称为静态外部变量,以免被其他文件误用。

           不要误认为用static声明的变量才采用静态存储方式(存放在静态存储区),而不加static的是动态存储,实际上,两种形式的外部变量都用静态存储方式,只是作用范围不同而已,都是在编译时分配内存的。

//another.cpp文件


static int a = 9;
//main.cpp文件
#include <iostream>
using namespace std;
//static int a = 10;
int main() {
	extern int a;
	cout << a << endl;
	return 0;
}

main.cpp文件不能使用another.cpp文件中的外部变量a,会报错。

猜你喜欢

转载自blog.csdn.net/qq_35294564/article/details/82627474