天天看點

c語言之靜态局部變量,靜态全局變量和靜态函數

c語言中需要記憶體來存放資料。而記憶體主要分為兩類:靜态存儲區和動态存儲區;

1.靜态存儲區分為:隻讀資料(READONLY  DATA)區、讀寫資料(RW DATA)區、未初始化區(BSS)。它們都是在程式編譯連接配接階段确定的,在程式執行的階段不會改變。

2.動态存儲區分為堆和棧。都是程式執行的過程中動态配置設定的,大小也随之動态變化。從記憶體管理的實作的角度看來,堆使用的連結清單實作的,而棧使用的是線性存儲的方法。

棧:棧是先進後出,實際的操作中,棧記憶體可以有滿棧和空棧的情況,滿棧的情況下,棧指針目前的位子是已經使用的的棧區域;空棧的情況是,棧指針目前的位子是沒有使用的棧區域,是以兩種情況的出入棧,指針和資料的操作先後順序是不同的。

滿棧時:入棧,是先移動指針,在放入資料;出棧則是先出資料,在移動指針;

空棧時:入棧,是先放入資料,在移動指針。出棧則是先移動指針,在出資料;

C語言必須注意的幾個問題:

1.記憶體洩露:申請一塊記憶體,但沒有釋放,程式結束也沒回收,導緻其他程式不能使用

2.野指針:指一個記憶體指針已經被釋放free或者realloc,但指針依然在使用。避免野指針的情況,将記憶體的指針置為NULL,并在程式使用的時候判斷該記憶體是否為NULL,如為空,則認為該記憶體已經釋放,不對記憶體進行通路。

3.非法釋放記憶體:原則上講隻有被malloc(),calloc()或realloc()配置設定并通過傳回值傳回傳回的記憶體才能被釋放,否則釋放除此以外的記憶體都是非法的。即使有一個指針是*p是malloc,那麼對p1=p++,這個時候free(p1)也是不合法的,但free(p)确實可以的。同樣釋放函數中的局部變量也是非法的.還有一種情況是,對一個堆記憶體釋放兩次也是錯誤的用法。因為free()函數是不能釋放未配置設定的堆記憶體。在程式使用free釋放記憶體之後,應該将指針置為NULL,free一個NULL位址是沒有問題的。

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(……)                        

  {……}