C++之——變量的存儲類別及static、register、extern用法

一、變量屬性

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,會報錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章