c c 靜態變數和靜態函式

2021-08-31 13:31:21 字數 3309 閱讀 5494

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

靜態儲存區分為:唯讀資料(readonly data)區、以讀寫資料(rw data)區、未初始化區(bss)。它們都是在程式編譯連線階段確定的,在程式執行的階段不會改變。

動態儲存區分為堆和棧。都是程式執行的過程中動態分配的,大小也隨之動態變化。從記憶體管理的實現的角度看來,堆使用的鍊錶實現的,而棧使用的是線性儲存的方法。

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

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

野指標:指乙個記憶體指標已經被釋放free或者realloc,但指標依然在使用。避免野指標的情況,將記憶體的指標置為null,並在程式使用的時候判斷該記憶體是否為null,如為空,則認為該記憶體已經釋放,不對記憶體進行訪問。

非法釋放記憶體:原則上講只有被malloc(),calloc()或realloc()分配並通過返回值返回返回的記憶體才能被釋放,否則釋放除此以外的記憶體都是非法的。即使有乙個指標是*p是malloc,那麼對p1=p++,這個時候free(p1)也是不合法的,但free( p) 確實可以的。同樣釋放函式中的區域性變數也是非法的.還有一種情況是,對乙個堆記憶體釋放兩次也是錯誤的用法。因為free()函式是不能釋放未分配的堆記憶體。在程式使用free釋放記憶體之後,應該將指標置為null,free乙個null位址是沒有問題的。

堆:用new分配,free釋放

自由儲存區:malloc分配,delete釋放

棧:編譯器管理的區域性變數和函式引數等。

全域性/靜態儲存區:儲存靜態變數和全域性變數

字元常量區:常量儲存的記憶體

也就是說static修飾函式的僅有乙個意思:就是告訴編譯器,我是乙個內部函式,不要隨便的用我。

static 變數

靜態變數的型別 說明符是static。 靜態變數當然是屬於靜態儲存方式,但是屬於靜態儲存方式的量不一定就是靜態變數。 例如外部變數雖屬於靜態 儲存方式,但不一定是靜態變數,必須由 static加以定義後才能成為靜態外部變數,或稱靜態全域性變數。

靜態區域性變數

靜態區域性變數屬於靜態儲存方式,它具有以下特點:

靜態全域性變數

全域性變數(外部變數)的說明之前再冠以static 就構 成了靜態的全域性變數。全域性變數本身就是靜態儲存方式, 靜態全域性變數當然也是靜態儲存方式。 這兩者在儲存方式上並無不同。這兩者的區別雖在於非靜態全域性 變數的作用域是整個源程式, 當乙個源程式由多個原始檔組成時,非靜態的全域性變數在各個原始檔中都是有效的。 而靜態全域性變數則限制了其作用域, 即只在 定義該變數的原始檔內有效, 在同一源程式的其它原始檔中不能使用它。由於靜態全域性變數的作用域侷限於乙個原始檔內,只能為該原始檔內的函式公用, 因此 可以避免在其它原始檔中引起錯誤。從以上分析可以看出, 把區域性變數改變為靜態變數後是改變了它的儲存方式即改變了它的生存期。把全域性變數改變為靜態變數 後是改變了它的作用域, 限制了它的使用範圍。因此static 這個說明符在不同的地方所起的作用是不同的。

static 函式……

內部函式和外部函式:當乙個源程式由多個原始檔組成時,c語言根據函式能否被其它原始檔中的函式呼叫,將函式分為內部函式和外部函式。

static  函式型別  函式名(函式引數表)

關鍵字「static」,譯成中文就是「靜態的」,所以內部函式又稱靜態函式。但此處「static」的含義不是指儲存方式,而是指對函式的作用域僅侷限於本檔案。使用內部函式的好處是:不同的人編寫不同的函式時,不用擔心自己定義的函式,是否會與其它檔案中的函式同名,因為同名也沒有關係。

外部函式

外部函式的定義:在定義函式時,如果沒有加關鍵字「static」,或冠以關鍵字「extern」,表示此函式是外部函式:

[extern] 函式型別 函式名(函式引數表)

呼叫外部函式時,需要對其進行說明:

[extern] 函式型別 函式名(引數型別表)[,函式名2(引數型別表2)……];

[案例]外部函式應用。

(1)檔案main.c

main()

(2)檔案subf1.c

extern  void input(……)                           /*定義外部函式*/

(3)檔案subf2.c

……

extern void process(……) /*定義外部 函式*/

(4)檔案subf3.c

……

extern void output(……) /*定義外部函式*/

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

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

c++靜態成員和靜態成員函式的使用:靜態成員的呼叫格式:類名::靜態資料成員名、物件名.靜態資料成員名、物件指標->靜態資料成員、物件引用.靜態資料成員(但類中很少會出現公有資料成員,這段僅僅討論語法,未考慮實際運用中的資料封裝問題)。靜態成員函式的呼叫格式:類名::靜態成員函式名、物件名.靜態成員函式名、物件指標->靜態成員函式名、物件引用.靜態資料成員。靜態成員函式沒有this指標,因它不與特定物件相聯絡,呼叫時推薦使用「類名::靜態成員函式名」格式。總結來說,在有物件的情況下,可以用呼叫普通類成員函式、普通成員變數的方式呼叫靜態成員函式和靜態成員變數。從這裡可以看出靜態成員變數和靜態成員函式的使用應該是在不建立任何物件的情況下呼叫它們。其應用可以參見設計模式中singleton pattern。

靜態變數和靜態函式

靜態變數 靜態變數使用 static 修飾符進行宣告 在所屬類被裝載時建立 通過類進行訪問 所屬類的所有例項的同一靜態變數都是同乙個值 非靜態變數 不帶有 static 修飾符宣告的變數稱做非靜態變數 在類被例項化時建立 通過物件進行訪問 同乙個類的不同例項的同一非靜態變數可以是不同的值 在c 中,...

靜態函式和靜態變數

記憶體大致可以劃分為 棧區堆區 全域性 靜態區 常量區 區 其中棧區位於高位址,區位於低位址。區 存放程式 段 常量區 存放各種常量 數值常量和字串常量等 全域性 靜態區 存放全域性變數和靜態變數,未初始化的和初始化的分開存放 堆區 使用new就是在該區申請 棧區 存放區域性變數等 a.件 clas...

JS靜態變數和靜態函式

function a 在建構函式外定義的都是所有物件共享的 a.id 我是a a.sayid function a.sayid 如上,在建構函式外用函式名定義的屬性或者方法,可以也只可以通過函式名來訪問,這和c 基本一樣。輸出 試圖訪問非靜態變數時 function a 在建構函式外定義的都是所有物...