您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“C語言棧、堆和靜態(tài)存儲(chǔ)區(qū)怎么使用”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“C語言棧、堆和靜態(tài)存儲(chǔ)區(qū)怎么使用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
棧是現(xiàn)代計(jì)算機(jī)程序里最為重要的概念之一
棧在程序中用于維護(hù)函數(shù)調(diào)用上下文
函數(shù)中的參數(shù)和局部變量存儲(chǔ)在棧上
棧保存了一個(gè)函數(shù)調(diào)用所需的維護(hù)信息
參數(shù)
返回地址
局部變量
調(diào)用上下文
每次函數(shù)調(diào)用都對(duì)應(yīng)著一個(gè)棧上的活動(dòng)記錄
調(diào)用函數(shù)的活動(dòng)記錄位于棧的中部
被調(diào)函數(shù)的活動(dòng)記錄位于棧的頂部
從main() 開始運(yùn)行
main() 調(diào)用 f()
當(dāng)從 f() 調(diào)用中返回 main()
函數(shù)調(diào)用時(shí),對(duì)應(yīng)的棧空間在函數(shù)返回前是專用的
函數(shù)調(diào)用結(jié)束后,??臻g將被釋放,數(shù)據(jù)不再有效
下面看一個(gè)指向棧數(shù)據(jù)的指針:
#include <stdio.h> int* g() { int a[10] = {0}; return a; } void f() { int i = 0; int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int *pointer = g(); for (i = 0; i < 10; i++) { b[i] = pointer[i]; } for(i = 0; i < 10; i++) { printf("%d\n", b[i]); } } int main() { f(); return 0; }
輸出結(jié)果如下:
如果把
for (i = 0; i < 10; i++)
{
b[i] = pointer[i];
}
注釋了,直接打印 pointer[i] 里面的數(shù)據(jù),如下:
#include <stdio.h> int* g() { int a[10] = {0}; return a; } void f() { int i = 0; int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int *pointer = g(); /* for (i = 0; i < 10; i++) { b[i] = pointer[i]; } */ for(i = 0; i < 10; i++) { printf("%d\n", pointer[i]); } } int main() { f(); return 0; }
輸出結(jié)果如下:
為什么直接打印 pointer[i] 里面的值會(huì)是這樣呢?因?yàn)?pointer 指向的空間是??臻g,??臻g在 g() 函數(shù)返回之后,活動(dòng)記錄就被釋放了。被釋放后調(diào)用 printf 函數(shù),printf 函數(shù)需要在棧上面建立一個(gè)活動(dòng)記錄。這個(gè)活動(dòng)記錄就會(huì)有 printf 函數(shù)的參數(shù)信息和返回值等,所以 pointer 所指向的內(nèi)存里面的數(shù)據(jù)由于 printf 函數(shù)的調(diào)用被改變了。因此,不能返回局部變量的地址,不能返回局部數(shù)組的數(shù)組名。
堆是程序中一塊預(yù)留的內(nèi)存空間,可由程序自由使用
堆中被程序申請(qǐng)使用的內(nèi)存在被主動(dòng)釋放前將一直有效
為什么有了棧還需要堆?
答:棧上的數(shù)據(jù)在函數(shù)返回后就會(huì)被釋放掉,無法傳遞到函數(shù)外部,如:局部數(shù)組
C語言程序中通過庫(kù)函數(shù)的調(diào)用獲得堆空間
頭文件:malloc.h
malloc -- 以字節(jié)的方式動(dòng)態(tài)申請(qǐng)堆空間
free -- 將堆空間歸還給系統(tǒng)
系統(tǒng)對(duì)堆空間的管理方式
空閑鏈表法,位圖法,對(duì)象池法等等
以 int* p = (int*)malloc(sizeof(int)); 為例,要申請(qǐng) 4 個(gè)字節(jié)的大小,遍歷之后發(fā)現(xiàn)跟 5 Bytes 這個(gè)節(jié)點(diǎn)最接近,找到一個(gè)可以用的單元之后,就將這個(gè)單元的地址返還給了 p 指針。以前也提過使用 malloc 申請(qǐng)內(nèi)存空間時(shí)返回的內(nèi)存空間可能比申請(qǐng)的實(shí)際內(nèi)存空間要大一點(diǎn)點(diǎn),原因就是在空閑鏈表管理堆空間這樣的系統(tǒng)里面,它會(huì)找最近的那個(gè),找到后的一般都大于等于所需要的內(nèi)存空間,假如 5 Bytes 這個(gè)節(jié)點(diǎn)下所有的空閑內(nèi)存單元都用完的話,就會(huì)找 12 Bytes 節(jié)點(diǎn)下的內(nèi)存單元,這樣malloc 返回的內(nèi)存空間就有可能比自己實(shí)際申請(qǐng)的內(nèi)存空間要大。
靜態(tài)存儲(chǔ)區(qū)隨著程序的運(yùn)行而分配空間
靜態(tài)存儲(chǔ)區(qū)的生命周期直到程序運(yùn)行結(jié)束
在程序的編譯期靜態(tài)存儲(chǔ)區(qū)的大小就已經(jīng)確定
靜態(tài)存儲(chǔ)區(qū)主要用于保存全局變量和靜態(tài)局部變量
靜態(tài)存儲(chǔ)區(qū)的信息最終會(huì)保存到可執(zhí)行程序中
下面看一個(gè)靜態(tài)存儲(chǔ)區(qū)的驗(yàn)證代碼:
#include <stdio.h> int g_v = 1; static int g_vs = 2; void f() { static int g_vl = 3; printf("%p\n", &g_vl); } int main() { printf("%p\n", &g_v); printf("%p\n", &g_vs); f(); return 0; }
輸出結(jié)果如下:
可以看到這三個(gè)地址是順序存放的,因?yàn)檫@三個(gè)變量都是存放在程序的靜態(tài)存儲(chǔ)區(qū),靜態(tài)存儲(chǔ)區(qū)在程序里面有固定的起始地址。
讀到這里,這篇“C語言棧、堆和靜態(tài)存儲(chǔ)區(qū)怎么使用”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。