C語言之static靜態變量

1. static 變量

靜態變量的類型 說明符是static。 靜態變量固然是屬於靜態存儲方式,可是屬於靜態存儲方式的量不必定就是靜態變量。 例如外部變量雖屬於靜態 存儲方式,但不必定是靜態變量,必須由 static加以定義後才能成爲靜態外部變量,或稱靜態全局變量。

2. 靜態局部變量
靜態局部變量屬於靜態存儲方式,它具備如下特色:
(1)靜態局部變量在函數內定義 它的生存期爲整個源程序,可是其做用域仍與自動變量相同,只能在定義該變量的函數內使用該變量。退出該函數後, 儘管該變量還繼續存在,但不能使用它。

(2)容許對構造類靜態局部量賦初值 例如數組,若未賦以初值,則由系統自動賦以0值。
(3) 對基本類型的靜態局部變量若在說明時未賦以初值,則系統自動賦予0值。而對自動變量不賦初值,則其值是不定的。 根據靜態局部變量的特色, 能夠 看出它是一種生存期爲整個源程序的量。雖然離開定義它的函數後不能使用,但如再次調用定義它的函數時,它又可繼續使用, 並且保存了前次被調用後留下的 值。 所以,當屢次調用一個函數且要求在調用之間保留某些變量的值時,可考慮採用靜態局部變量。雖然用全局變量也能夠達到上述目的,但全局變量有時會形成 意外的反作用,所以仍以採用局部靜態變量爲宜。

3.靜態全局變量
全局變量(外部變量)的說明以前再冠以static 就構 成了靜態的全局變量。全局變量自己就是靜態存儲方式, 靜態全局變量固然也是靜態存儲方式。 這二者在存儲方式上並沒有不一樣。這二者的區別雖在於非靜態全局 變量的做用域是整個源程序, 當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其做用域, 即只在 定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。因爲靜態全局變量的做用域侷限於一個源文件內,只能爲該源文件內的函數公用, 所以 能夠避免在其它源文件中引發錯誤。從以上分析能夠看出, 把局部變量改變爲靜態變量後是改變了它的存儲方式即改變了它的生存期。把全局變量改變爲靜態變量 後是改變了它的做用域, 限制了它的使用範圍。所以static 這個說明符在不一樣的地方所起的做用是不一樣的。

4. static 函數…..

內部函數和外部函數

當一個源程序由多個源文件組成時,C語言根據函數可否被其它源文件中的函數調用,將函數分爲內部函數和外部函數。
1 內部函數(又稱靜態函數)
若是在一個源文件中定義的函數,只能被本文件中的函數調用,而不能被同一程序其它文件中的函數調用,這種函數稱爲內部函數。
定義一個內部函數,只需在函數類型前再加一個「static」關鍵字便可,以下所示:
static 函數類型 函數名(函數參數表)
{……}
關鍵字「static」,譯成中文就是「靜態的」,因此內部函數又稱靜態函數。但此處「static」的含義不是指存儲方式,而是指對函數的做用域僅侷限於本文件。
使用內部函數的好處是:不一樣的人編寫不一樣的函數時,不用擔憂本身定義的函數,是否會與其它文件中的函數同名,由於同名也沒有關係。

2 外部函數
外部函數的定義:在定義函數時,若是沒有加關鍵字「static」,或冠以關鍵字「extern」,表示此函數是外部函數:
[extern] 函數類型 函數名(函數參數表)
{……}
調用外部函數時,須要對其進行說明:
[extern] 函數類型 函數名(參數類型表)[,函數名2(參數類型表2)……];

[案例]外部函數應用。
(1)文件mainf.c
main()
{ extern void input(…),process(…),output(…);
input(…); process(…); output(…);
}

(2)文件subf1.c
……
extern void input(……) /*定義外部函數*/
{……}
(3)文件subf2.c
……
extern void process(……) /*定義外部 函數*/
{……}
(4)文件subf3.c
……
extern void output(……) /*定義外部函數*/
{……}


一、概述

  static 聲明的變量在C語言中有兩方面的特徵:

  1)、變量會被放在程序的全局存儲區中,這樣能夠在下一次調用的時候還能夠保持原來的賦值。這一點是它與堆棧變量和堆變量的區別。  2)、變量用static告知編譯器,本身僅僅在變量的做用範圍內可見。這一點是它與全局變量的區別。

  二、問題:Static的理解

  關於static變量,請選擇下面全部說法正確的內容:

  A、若全局變量僅在單個C文件中訪問,則能夠將這個變量修改成靜態全局變量,以下降模塊間的耦合度;

  B、若全局變量僅由單個函數訪問,則能夠將這個變量改成該函數的靜態局部變量,以下降模塊間的耦合度;

  C、設計和使用訪問動態全局變量、靜態全局變量、靜態局部變量的函數時,須要考慮重入問題;

  D、靜態全局變量過大,可那會致使堆棧溢出。

  答案與分析:

  對於A,B:根據本篇概述部分的說明b),咱們知道,A,B都是正確的。

  對於C:根據本篇概述部分的說明a),咱們知道,C是正確的(所謂的函數重入問題,下面會詳細闡述)。

  對於D:靜態變量放在程序的全局數據區,而不是在堆棧中分配,因此不可能致使堆棧溢出,D是錯誤的。

  所以,答案是A、B、C。

  三、問題:不可重入函數

  曾經設計過以下一個函數,在代碼檢視的時候被提醒有bug,由於這個函數是不可重入的,爲何?

unsigned int sum_int( unsigned int base ) {  unsigned int index;  static unsigned int sum = 0; // 注意,是static類型的。  for (index = 1; index <= base; index++)  {   sum += index;  }  return sum; }
  答案與分析:   所謂的函數是可重入的(也能夠說是可預測的),即:只要輸入數據相同就應產生相同的輸出。  這個函數之因此是不可預測的,就是由於函數中使用了static變量,由於static變量的特徵,這樣的函數被稱爲:帶「內部存儲器」功能的的函數。 所以若是咱們須要一個可重入的函數,那麼,咱們必定要避免函數中使用static變量,這種函數中的static變量,使用原則是,能不用盡可能不用。   將上面的函數修改成可重入的函數很簡單,只要將聲明sum變量中的static關鍵字去掉,變量sum即變爲一個auto 類型的變量,函數即變爲一個可重入的函數。   固然,有些時候,在函數中是必需要使用static變量的,好比當某函數的返回值爲指針類型時,則必須是static的局部變量的地址做爲返回值,若爲auto類型,則返回爲錯指針。
相關文章
相關標籤/搜索