C 語言程式設計 堆疊與記憶體管理

2021-10-04 18:13:04 字數 4110 閱讀 4128

記憶體管理

動態分配記憶體

重新調整記憶體的大小和釋放記憶體

malloc 函式詳解

memset 初始化記憶體資料

《程式編譯流程與 gcc 編譯器》

《c 語言程式設計 — 基本語法》

《c 語言程式設計 — 基本資料型別》

《c 語言程式設計 — 變數與常量》

《c 語言程式設計 — 運算子》

《c 語言程式設計 — 邏輯控制語句》

《c 語言程式設計 — 函式》

《c 語言程式設計 — 高階資料型別 — 指標》

《c 語言程式設計 — 高階資料型別 — 陣列》

《c 語言程式設計 — 高階資料型別 — 字串》

《c 語言程式設計 — 高階資料型別 — 列舉》

《c 語言程式設計 — 高階資料型別 — 結構體與位域》

《c 語言程式設計 — 高階資料型別 — 共用體》

《c 語言程式設計 — 高階資料型別 — void 型別》

《c 語言程式設計 — 資料型別的別名》

《c 語言程式設計 — 資料型別轉換》

《c 語言程式設計 — 巨集定義與預處理器指令》

《c 語言程式設計 — 異常處理》

《c 語言程式設計 — 標頭檔案》

《c 語言程式設計 — 輸入/輸出與檔案操作》

c 語言的設計者把記憶體簡單粗暴地想象成乙個巨大的位元組(byte)陣列。事實上,它被更加合理地劃分成了兩部分,即棧和堆。實際上,它們只是記憶體中的兩塊不同的區域,分別用來完成不同的任務而已。

棧是程式賴以生存的地方,所有的臨時變數和資料結構都儲存於其中,供你讀取及編輯。每次呼叫乙個新的函式,就會有一塊新的棧區壓入,並在其中存放函式內的臨時變數、傳入的實參的拷貝以及其它的一些資訊。當函式執行完畢,這塊棧區就會被彈出並**,供其他函式使用。

堆佔據另一部分記憶體,主要用來存放長生命週期期的資料。堆中的資料必須手動申請和釋放

申請記憶體使用 malloc 函式。這個函式接受乙個數字作為要申請的位元組數,返回申請好的記憶體塊的指標。當使用完畢申請的記憶體,我們還需要將其釋放,只要將 malloc 函式返回的指標傳給 free 函式即可。

堆比棧的使用難度要大一些,因為它要求程式設計師手動呼叫 free 函式釋放記憶體,而且還要正確呼叫。如果不釋放,程式就有可能不斷申請新的記憶體,而不釋放舊的,導致記憶體越用越多。這也被稱為記憶體洩漏。避免這種情況發生的乙個簡單有效的辦法就是,針對每乙個 malloc 函式呼叫,都有且只有乙個 free 函式與之對應。這某種程度上就能保證程式能正確處理堆記憶體的使用。

我把堆想象成乙個自助儲存倉庫,我們使用 malloc 函式申請儲存空間。我們可以在自主儲存倉庫和建築工地之間自由訪問。它非常適合用來存放大件的偶爾才用一次的物件。唯一的問題就是在用完之後要記得使用 free 函式將空間歸還。

c 語言為記憶體的分配和管理提供了幾個標準函式。這些函式可以在 stdlib.h 標頭檔案中找到。

注:void *型別表示未確定型別的指標。c、c++ 規定void *型別可以通過強制型別轉換為任何其它型別的指標。

#include

#include

#include

intmain()

else

printf

("name = %s\n"

, name)

;printf

("description: %s\n"

, description)

;return0;

}

執行:

$ ./main

name = zara ali

description: zara ali a dps student in class 10th

上面的程式也可以使用calloc()函式來編寫,只需要把 malloc 替換為 calloc 即可:

calloc

(200

,sizeof

(char))

;

當動態分配記憶體時,程式有完全控制權,可以傳遞任何大小的值。不同的是,那些預先定義了大小的陣列,一旦定義則無法改變大小。

當程式退出時,作業系統會自動釋放所有分配給程式的記憶體,但是主動釋放記憶體是乙個良好的程式設計習慣。

#include

#include

#include

intmain()

else

/* 擴充套件分配記憶體,記憶體大小為 100 個字元長度(8 bit)。

函式呼叫返回記憶體的指標(位址)並強制型別轉換為字元指標型別。

*/description =

(char*)

realloc

(description,

100*

sizeof

(char))

;if(description ==

null

)else

printf

("name = %s\n"

, name)

;printf

("description: %s\n"

, description)

;/* 釋放記憶體 */

free

(description)

;return0;

}

執行:

$ ./main

name = zara ali

description: zara ali a dps student in class 10th

she is in class 10th

函式原型:

void

*malloc

(size_t size)

;

int

*p;p =

(int*)

malloc

(sizeof

(int))

;

簡而言之,malloc 函式其實就是在記憶體中找到一片指定大小的、邏輯連續的記憶體空間,然後將這個空間的首位址給乙個指標變數,這裡的指標變數可以是乙個單獨的指標,也可以是乙個陣列的首位址,具體要看 size_t size 實參的具體內容。

int

*arr;

arr =

(int*)

malloc

(sizeof

(int)*

10);

在 c 語言程式設計匯中應該要保持乙個習慣:定義變數時一定要進行初始化,尤其是陣列和結構體這種占用記憶體大的資料結構。因為在使用陣列或分配記憶體時,程式得到的只是乙個記憶體空間的位址,實際上記憶體空間的值並非一直是 「乾淨」 的,在沒有初始化的情況下,經常會因為髒資料而產生亂碼。

c 語言中,每種資料型別的變數都有各自的初始化方法,為 memset 函式可以說是初始化記憶體的萬能函式,作用是在一段記憶體塊中填充某個給定的值,通常用於為新申請的記憶體或陣列進行初始化工作。

函式原型:將指標變數 s 所指向的前 n 位元組的記憶體單元用乙個 int 型別 c(通常為 0)替換。其中,n 通常是使用 sizeof 獲取的,因為 s 是 void* 型的指標變數,所以它可以為任何型別的資料進行初始化。用 memset 初始化完後,後續的**中再向該記憶體空間中存放預期的資料。

#include

void

*memset

(void

*s,int c,

unsigned

long n)

;

示例

#include

#include

intmain

(void

)printf

("\n");

return0;

}

C 堆 棧與記憶體管理

一 所謂stack和heap 例子 class complex 作用域 scope stack 儲存區域性變數或臨時物件的一塊記憶體,函式呼叫結束會消失 heap 存放全域性物件或變數的記憶體空間,函式呼叫結束如果不通過delete 釋放將直到程式執行結束之前一直存在。二 static local ...

C 侯捷 堆 棧與記憶體管理

class complex complex c3 1,2 void main stack棧 是存在於魔偶作用域的一塊記憶體空間,函式本身會形成乙個stack,存放接收的引數和返回位址以及local object。c1所用的空間來自stack。器生命在作用域之內有效,會自動清理,析構函式自動呼叫。st...

c語言記憶體管理

在c語言中,根據資料在記憶體中存在的時間 生存期 不同,將記憶體空間分為三個區 1.程式區 用於儲存程式的 即程式的二進位制 存放函式體的二進位制 2.靜態儲存區 用於儲存全域性變數和靜態變數,這些變數的空間在程式編譯時就已經分配好了.全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態...