深入理解c語言指標 第三章

2021-08-13 11:29:06 字數 3186 閱讀 3106

背景:要理解函式及其和指標的結合使用,需要理解程式棧。大部分現代的塊結構語言,比如c,都用到了程式棧來支援函式執行。呼叫函式時,會建立函式的棧幀並將其推到程式棧上。函式返回時,其棧幀從程式棧上彈出。

注意 區域性變數也稱為自動變數,它們總是分配在棧幀上。

一些名詞:

1. 程式棧

2. 棧幀

3. 堆

4. 棧

程式棧是支援函式執行的記憶體區域,通常和堆共享。也就是說,它們共享同一塊記憶體區域。程式棧通常佔據這塊區域的下部,而堆用的則是上部。

程式棧存放棧幀(stack frame),棧幀有時候也稱為活躍記錄(activation record)或活躍幀(activation frame)。棧幀存放函式引數和區域性變數

呼叫函式時,函式的棧幀被推到棧上,棧向上「長出」乙個棧幀。當函式終止時,其棧幀從程式棧上彈出。棧幀所使用的記憶體不會被清理,但最終可能會被推到程式棧上的另乙個棧幀覆蓋。

呼叫函式時,函式的棧幀被推到棧上,棧向上「長出」乙個棧幀。當函式終止時,其棧幀從程式棧上彈出。棧幀所使用的記憶體不會被清理,但最終可能會被推到程式棧上的另乙個棧幀覆蓋。

棧幀由以下幾種元素組成

返回位址(函式完成後要返回的程式內部位址。)

區域性資料儲存(為區域性變數分配的記憶體。)

引數儲存(為函式引數分配的記憶體。)

棧指標和基指標(執行時系統用來管理棧的指標。)

總結和理順上面的東西:

一、堆和棧

首先要清楚的是程式對記憶體的使用分為以下幾個區:

l 棧區(stack):由編譯器自動分配和釋放,存放函式的引數值,區域性變數的值等。操作方式類似於資料結構中的棧。

l 堆區(heap):一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時可能由作業系統**。與資料結構中的堆是兩碼事,分配方式類似於鍊錶。

l 全域性區(static):全域性變數和靜態變數存放在此。

l 文字常量區:常量字串放在此,程式結束後由系統釋放。

l 程式**區:存放函式體的二進位制**。

典型的記憶體區域分配如圖所示:

棧幀和程式棧都位於堆上

指標和函式

傳入指標

void swapwithpointers(int* pnum1, int* pnum2)

傳入指向常量的指標

void passingaddressofconstants(const int* num1, int* num2)

返回指標

通常用到下面兩種技術

1. 使用malloc在函式內部分配記憶體並返回其位址。呼叫者負責釋

放返回的記憶體。

2. 傳遞乙個物件給函式並讓函式修改它。這樣分配和釋放物件的

記憶體都是呼叫者的責任

// 使用malloc

int* allocatearray(int size, int

value) r

eturn arr;

}

問題:區域性資料指標

int* allocatearray(int

size, int value) r

eturn arr;

}

雖然返回arr,陣列的每一項都能訪問得到,但是如果再來乙個函式,可能會覆蓋arr,因為arr在函式結束後就被**了

如下圖:

指向指標的指標的案例

void allocatearray(int **arr, int size, int value) 

}

不要把返回指標的函式和函式指標搞混。

下面的f4是乙個函式,它返回乙個整數指標,

而f5是乙個返回整數的函式指標,

變數f6是乙個返回整數指標的函式指標。

int*f4();

int (*f5)();

int* (*f6)();

//使用函式指標

#include

#include

//申明乙個函式指標

int (*foo)(int);

int square(int i)

int main(int argc, char *argv)

傳遞函式指標

#include 

#include

int add(int num1, int num2)

int subtract(int num1, int num2)

typedef

int (*fptroperation)(int,int);

int compute(fptroperation operation, int num1, int num2)

int main(int argc, char *argv)

返回函式指標

#include 

#include

int add(int num1, int num2)

int subtract(int num1, int num2)

typedef

int (*fptroperation)(int,int);

fptroperation select(char opcode)

}int evaluate(char opcode, int num1, int num2)

int main(int argc, char *argv)

3.3.5節後面好像不怎麼使用,以後用到函式與有關指標的時候在看吧

《深入理解C 》 高階泛型(第三章)

1 靜態字段 從屬於宣告它的型別,每個封閉型別都有它自己的靜態欄位集 定義包含靜態欄位的泛型型別 public class typewithfield 呼叫 typewithfield.field first typewithfield.field second typewithfield.fiel...

C語言第三章

main.c project1 created by sihan guo on 2019 06 13.include int main int argc,const char ar else 迴圈結構 當型 int icount 5 while icount 0 直到型迴圈結構 這個迴圈結構至少執行...

深入理解計算機系統 第三章

1.假設過程p 呼叫者 呼叫過程q 被呼叫者 則q的引數放在p的棧幀中。2.另外,當p呼叫q時,p中的返回位址被壓入棧中,形成p的棧幀的末尾。3.返回位址就是當程式從q返回時應該繼續執行的地方。程式暫存器組是唯一能夠被所有過程共享的資源。雖然在給定時刻只能有乙個過程是活動的,但是我們必須保證當乙個過...