程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> static作用:靜態變量的生存周期和作用域

static作用:靜態變量的生存周期和作用域

編輯:C++入門知識

首先要理解生存周期與作用域的區別:

生存周期: 變量從定義到銷毀的時間范圍。存放在全局數據區的變量的生存周期存在於整個程序運行期間,而存放在棧中的數據則隨著函數等的作用域結束導致出棧而銷毀,除了靜態變量之外的局部變量都存放於棧中。

作用域: 變量的可見代碼域(塊作用域,函數作用域,類作用域,程序全局作用域)。

 


static變量是指靜態的變量,不管是在全局還是局部聲明的static變量都存放於程序的全局變量區域,所以它的生命周期是從程序開始到程序結束。但是static變量的作用域並不等同於它的生存周期,它的作用域決定於它被定義的位置。可以認為static變量的作用域<=生存周期。

 


舉一個局部聲明的例子。在函數test中聲明靜態變量i:

void test()

{

int m=3;

static int i=5;

}

局部變量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局部變量和普通局部變量有什麼區別 ?

   把局部變量改變為靜態變量後是改變了它的存儲方式即改變了它的生存期。把全局變量改變為靜態變量後是改變了它的作用域,限制了它的使用范圍。 

  static局部變量只被初始化一次,下一次依據上一次結果值;  

3.  static函數與普通函數有什麼區別?

   static函數與普通函數作用域不同,僅在本文件。只在當前源文件中使用的函數應該說明為內部函數(static修飾的函數),內部函數應該在當前源文件中說明和定義。對於可在當前源文件以外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件.

static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝

 

 


P.S.

C程序一直由下列部分組成:
  1)正文段(代碼段)——CPU執行的機器指令部分;一個程序只有一個副本;只讀,防止程序由於意外事故而修改自身指令;   
  2)初始化數據段(數據段)——在程序中所有賦了初值的全局變量,存放在這裡。   
  3)非初始化數據段(bss段)——在程序中沒有初始化的全局變量;內核將此段初始化為0。(這就是為什麼全局內置類型變量會初始化,而局部變量就為未初始化的未知值)    
  4)棧——增長方向:自頂向下增長;自動變量以及每次函數調用時所需要保存的信息(返回地址;環境信息)。     
  5)堆——動態存儲分。

程序在內存中申請了代碼段,全局數據段(初始化和未初始化),棧和堆:程序代碼放於代碼段,全局變量和靜態變量存放在全局數據段中,一直存在直到程序結束,而局部變量都放於臨時的棧中,隨著作用域的結束隨著出棧操作而銷毀。malloc和new出來的內存不屬於上面提到的程序申請的內存中,而是在系統中申請到的內存,所以如果在程序中沒有明確free和delete的話,程序結束後該內存仍不會被釋放,造成內存洩漏。例如:

int test()

{

int * p=new int(3);

}

則test函數結束後,p指針本身被銷毀,因為它是存在於函數棧中的局部變量,而p指向的int整型內容仍存在於內容堆中,沒有被釋放,造成內存洩漏。

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved