寫在開頭
對於很多C/C++的初學者來說,很容易理不清變量的作用域和存儲類型這一塊的一些概念,也容易將其中的一些概念搞混淆。作為一個C/C++的初學者,筆者希望在這里能夠嘗試着去理一理這些較為繁雜的概念,主要當作自己備忘之用。當然,由於筆者水平有限,經驗不足,在這里也只能羅列一些常用概念和使用方法,且可能會有些許不專業之處,望君理解並指正。
一定要把變量的作用域和存儲類型分開來看
很多人很容易把變量的作用於和存儲類型搞混,但其實只要我們從它們定義出發來看,這個問題是很容易解決的。作用域是一個變量能夠被使用的范圍,而存儲類型則是變量的存儲方式,且存儲類型決定着變量的生存期。
通俗地講,存儲類型決定着一個變量在某位置存不存在,而作用域決定着一個變量在某位置能不能被使用。比如:
1 /*例1*/ 2 #include<stdio.h> 3 int main() 4 { 5 static int a=1;//定義了一個靜態存儲的局部變量 6 return 0; 7 }
a是一個采用靜態存儲的局部變量,像這樣的變量在整個文件中都不會消失,但是只能在main()函數內被使用。
作用域類型
在C語言中有塊作用域、函數作用域、函數原型作用域,以及文件作用域,在C++中還有類作用域和命名空間作用域。由於在各類資料中關於這幾類作用域的介紹已經相當豐富,在此我就不展開介紹了。在這幾類作用域中,除了函數作用域均可根據名稱來理解,如“具有塊作用域”就是說明該變量在對應代碼塊(一般來說就是大括號里包起來的部分,可以省略大括號的for語句、if()語句等除外)中能夠被使用。
函數作用域僅用於goto語句的標簽,由於goto語句已經用得很少,在此筆者不再對函數作用域進行展開介紹。
存儲類型
存儲類型分為靜態存儲和動態存儲,采用靜態存儲方式的變量一旦創建,其存儲空間在整個程序的運行過程中都不會被釋放。對於采用動態存儲的變量來說,當進入該程序塊(函數或復合語句等)時,建立該變量,分配存儲空間,當退出該程序塊時,撤銷該變量,釋放其存儲空間。
在接下來的一部分內容里,筆者將按照不同的限定詞來對各種常見情況進行分別描述。
不用限定詞的情況
1 /*例2,不用限定詞的情況*/ 2 #include<stdio.h> 3 int a=1;//a為全局變量,采用靜態存儲 4 int main() 5 { 6 int b=1;//b為局部變量,默認采用動態存儲 7 return 0; 8 }
全局變量a采用靜態方式存儲,具有文件作用域,b采用動態方式存儲,具有的是塊作用域。
使用static
1 /*例3*/ 2 #include<stdio.h> 3 static int a=1; 4 int main() 5 { 6 static int b=1; 7 return 0; 8 }
在程序塊外使用static來定義變量
如例3中的變量a。
對於全局變量來說,加不加static,該變量都采取靜態方式來存儲,但是加了static之后,該變量便變成了“內部變量”,即該變量只能在該文件內被使用。不加static的全局變量默認為“外部變量”,可以被其他文件在進行了引用申明(用extern,稍后介紹)后使用。
在程序塊內使用static來定義變量
如例3中的變量b。
對於定義局部變量來說,如果不加任何修飾詞,則該變量默認為自動變量,采取動態方式進行存儲。在用static進行修飾的變量定義中,該變量將采取靜態方式進行存儲,而且其初始化在編譯時進行,且只會進行一次。
但是,不管加不加static,在程序塊內定義的變量都只具有塊作用域。
使用extern
1 /*例4 part 1*/ 2 /*file 1.c*/ 3 #include<stdio.h> 4 int a=1; 5 static int b=1; 6 int main() 7 { 8 extern int c;//對於全局變量c做提前引用說明 9 printf("%d",c); 10 return 0; 11 } 12 int c=1;
1 /*例4,part 2*/ 2 /*file 2.c*/ 3 #include<stdio.h> 4 extern int a;//對全局變量a做引用申明 5 extern int b;//本行錯誤,因為b僅在file 1.c中有效 6 int main() 7 { 8 printf("%d",a); 9 return 0; 10 }
extern僅用於對全局變量進行引用聲明,其中包括對在定義在使用處后邊的全局變量做提前引用聲明(如例4 part 1 第8行),也包括在一個文件中對另一個文件里定義的全局外部變量做引用聲明(如例4 part 2 第4行)。
使用auto、register
使用auto可顯示地聲明自動變量,由於在程序塊內聲明的變量默認是auto的,所以auto更多地也就只是起到一個標記的作用了。
使用register可以將一些將被頻繁使用的局部變量放到寄存器中,這樣可以提高程序執行的效率。
