C語言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地址是沒有問題的。

 

c中:

在介紹之前,先討論一下 堆,棧,自由存儲區,全局/靜態存儲區和常量存儲區
堆:用new分配,free釋放
自由存儲區:malloc分配,delete釋放
棧:編譯器管理的局部變量和函數參數等。
全局/靜態存儲區:存儲靜態變量和全局變量
字符常量區:常量存儲的內存
也就是說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(……)                        /*定義外部函數*/
  {……}

C++中的靜態成員變量和靜態成員函數

  (1)類靜態數據成員在編譯時創建並初始化:在該類的任何對象建立之前就存在,不屬於任何對象,而非靜態類成員變量則是屬於對象所有的。類靜態數據成員只有一個拷貝,為所有此類的對象所共享。特別需要注意的一點是:靜態數據成員不能在類中初始化(對於常量靜態類變量有待考證,好像可以在類外或main()函數之前定義,初始化可以放在類中),一般在類外和main()函數之前初始化,缺省時初始化為0。靜態數據成員用來定義類的各個對象所公有的數據,比全局變量更安全。

  (2)類靜態成員函數屬於整個類,不屬於某個對象,由該類所有對象共享。靜態成員可定義為inline函數。一般情況下靜態成員函數用於訪問同一類中的靜態數據成員或全局變量,而不訪問非靜態成員,如需訪問非靜態成員,需要將對象作為參數,通過對象名訪問該對象的非靜態成員。靜態成員函數也可以在類外定義,此時不可以用static修飾。靜態成員函數存在的原因是什么呢?主要是在建立任何對象之前可用它來訪問靜態數據成員,普通函數不能實現此功能。

  C++靜態成員和靜態成員函數的使用:靜態成員的調用格式:類名::靜態數據成員名、對象名.靜態數據成員名、對象指針->靜態數據成員、對象引用.靜態數據成員(但類中很少會出現公有數據成員,這段僅僅討論語法,未考慮實際運用中的數據封裝問題)。靜態成員函數的調用格式:類名::靜態成員函數名、對象名.靜態成員函數名、對象指針->靜態成員函數名、對象引用.靜態數據成員。靜態成員函數沒有this指針,因它不與特定對象相聯系,調用時推薦使用“類名::靜態成員函數名”格式。總結來說,在有對象的情況下,可以用調用普通類成員函數、普通成員變量的方式調用靜態成員函數和靜態成員變量。從這里可以看出靜態成員變量和靜態成員函數的使用應該是在不建立任何對象的情況下調用它們。其應用可以參見設計模式中Singleton pattern。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM