首先要理解生存週期與作用域的區別:
生存週期: 變數從定義到銷毀的時間範圍。存放在全域性資料區的變數的生存週期存在於整個程式執行期間,而存放在棧中的資料則隨著函式等的作用域結束導致出棧而銷毀,除了靜態變數之外的區域性變數都存放於棧中。
作用域: 變數的可見**域(塊作用域,函式作用域,類作用域,程式全域性作用域)。
static變數是指靜態的變數,不管是在全域性還是區域性宣告的static變數都存放於程式的全域性變數區域,所以它的生命週期是從程式開始到程式結束。但是static變數的作用域並不等同於它的生存週期,它的作用域決定於它被定義的位置。可以認為static變數的作用域<=生存週期。
舉乙個區域性宣告的例子。在函式test中宣告靜態變數i:
void test()
區域性變數m存放在棧中,當test函式結束,m將被銷毀;靜態變數i不存放在棧中,而是存放於程式的全域性變數區域,因此隨著函式test的結束,它並不隨著出棧操作而被銷毀,它的生存週期存在於程式的整個執行期;然而m和i的作用域都僅存在於test函式中它們的定義之後,即test呼叫結束之後,m和i就不再可用,但是i仍存在於記憶體之中。
再舉乙個全域性宣告的例子。在檔案a 中定義靜態變數j:
int n=3; //預設為extern
static
int j=5; //宣告為static
全域性變數和靜態變數j都存放於程式的全域性資料區域,它們的生存週期都是程式的整個執行期,但是n的作用域為全域性作用域,可以通過extern在其他檔案中使用,而j只能在檔案a中使用,例如在檔案b中:
extern
int n; //ok
extern
int j; //error: j在檔案b中不可見
int a=n;//ok:但這裡有個初始化先後的問題,具體參見參考一
int b=j;//error
也就是說,在宣告全域性的static變數時,static沒有改變它的生存週期,也即儲存位置(因為全域性變數本來就儲存在全域性資料域),而是將變數的作用域限制在當前檔案中。
中興通訊2012校招筆試題的一道問答題:
1. static全域性變數與普通的全域性變數有什麼區別 ?
全域性變數(外部變數)的說明之前再冠以static 就構成了靜態的全域性變數。
全域性變數本身就是靜態儲存方式, 靜態全域性變數當然也是靜態儲存方式。 這兩者在儲存方式上並無不同。
這兩者的區別在於非靜態全域性變數的作用域是整個源程式, 當乙個源程式由多個原始檔組成時,非靜態的全域性變數在各個原始檔中都是有效的。 而靜態全域性變數則限制了其作用域, 即只在定義該變數的原始檔內有效, 在同一源程式的其它原始檔中不能使用它。由於靜態全域性變數的作用域侷限於乙個原始檔內,只能為該原始檔內的函式公用,因此可以避免在其它原始檔中引起錯誤。
static全域性變數只初使化一次,防止在其他檔案單元中被引用;
2. static區域性變數和普通區域性變數有什麼區別 ?
把區域性變數改變為靜態變數後是改變了它的儲存方式即改變了它的生存期。把全域性變數改變為靜態變數後是改變了它的作用域,限制了它的使用範圍。
3. static函式與普通函式有什麼區別?
static函式與普通函式作用域不同,僅在本檔案。只在當前原始檔中使用的函式應該說明為內部函式(static修飾的函式),內部函式應該在當前原始檔中說明和定義。對於可在當前原始檔以外使用的函式,應該在乙個標頭檔案中說明,要使用這些函式的原始檔要包含這個標頭檔案.
static函式在記憶體中只有乙份,普通函式在每個被呼叫中維持乙份拷貝
tips:
1.若全域性變數僅在單個c檔案中訪問,則可以將這個變數修改為靜態全域性變數,以降低模組間的耦合度;
2.若全域性變數僅由單個函式訪問,則可以將這個變數改為該函式的靜態區域性變數,以降低模組間的耦合度;
3.設計和使用訪問動態全域性變數、靜態全域性變數、靜態區域性變數的函式時,需要考慮重入問題,因為他們都放在靜態資料儲存區,全域性可見;
4.如果我們需要乙個可重入的函式,那麼,我們一定要避免函式中使用static變數(這樣的函式被稱為:帶「內部儲存器」功能的的函式)
5.函式中必須要使用static變數情況:比如當某函式的返回值為指標型別時,則必須是static的區域性變數的位址作為返回值,若為auto型別,則返回為錯指標。
p.s.
c程式一直由下列部分組成:
1)正文段(**段)——cpu執行的機器指令部分;乙個程式只有乙個副本;唯讀,防止程式由於意外事故而修改自身指令;
2)初始化資料段(資料段)——在程式中所有賦了初值的全域性變數,存放在這裡。
3)非初始化資料段(bss段)——在程式中沒有初始化的全域性變數;核心將此段初始化為0。(這就是為什麼全域性內建型別變數會初始化,而區域性變數就為未初始化的未知值)
4)棧——增長方向:自頂向下增長;自動變數以及每次函式呼叫時所需要儲存的資訊(返回位址;環境資訊)。
5)堆——動態儲存分。
程式在記憶體中申請了**段,全域性資料段(初始化和未初始化),棧和堆:程式**放於**段,全域性變數和靜態變數存放在全域性資料段中,一直存在直到程式結束,而區域性變數都放於臨時的棧中,隨著作用域的結束隨著出棧操作而銷毀。malloc和new出來的記憶體不屬於上面提到的程式申請的記憶體中,而是在系統中申請到的記憶體,所以如果在程式中沒有明確free和delete的話,程式結束後該記憶體仍不會被釋放,造成記憶體洩漏。例如:
int test()
則test函式結束後,p指標本身被銷毀,因為它是存在於函式棧中的區域性變數,而p指向的int整型內容仍存在於內容堆中,沒有被釋放,造成記憶體洩漏。 static作用 靜態變數的生存週期和作用域
首先要理解生存週期與作用域的區別 生存週期 變數從定義到銷毀的時間範圍。存放在全域性資料區的變數的生存週期存在於整個程式執行期間,而存放在棧中的資料則隨著函式等的作用域結束導致出棧而銷毀,除了靜態變數之外的區域性變數都存放於棧中。作用域 變數的可見 域 塊作用域,函式作用域,類作用域,程式全域性作用...
static作用 靜態變數的生存週期和作用域
首先要理解生存週期與作用域的區別 生存週期 變數從定義到銷毀的時間範圍。存放在全域性資料區的變數的生存週期存在於整個程式執行期間,而存放在棧中的資料則隨著函式等的作用域結束導致出棧而銷毀,除了靜態變數之外的區域性變數都存放於棧中。作用域 變數的可見 域 塊作用域,函式作用域,類作用域,程式全域性作用...
static作用 靜態變數的生存週期和作用域
首先要理解生存週期與作用域的區別 生存週期 變數從定義到銷毀的時間範圍。存放在全域性資料區的變數的生存週期存在於整個程式執行期間,而存放在棧中的資料則隨著函式等的作用域結束導致出棧而銷毀,除了靜態變數之外的區域性變數都存放於棧中。作用域 變數的可見 域 塊作用域,函式作用域,類作用域,程式全域性作用...