指標作為引數

2021-05-25 05:14:34 字數 1656 閱讀 5283

值傳遞, 指標傳遞?

這幾天在學習c過程中,在使用指標作為函式引數傳遞的時候出現了問題,根本不知道從何得解:源**如下:

createnode(binnode *tree,char *p)

該**段的意圖是通過乙個函式建立乙個二叉樹的節點,然而在,呼叫該函式後,試圖訪問該節點結構體的成員時候,卻發生了記憶體訪問錯誤,到底問題出在哪兒呢?

一直不明白指標作為函式引數傳值的機制,翻開林銳的《高質量c/c++程式設計指南》,找到了答案。

原來問題出在c編譯器原理上:編譯器總是要為函式的每個引數製作臨時副本,指標引數tree的副本是 _tree,編譯器使 _tree = tree。如果函式體內的程式修改了_tree的內容,就導致引數tree的內容作相應的修改。這就是指標可以用作輸出引數的原因。

即上面的函式**經過編譯後成為:

createnode(binnode *tree,char *p)

如果沒有

_tree = (binnode *) malloc(sizeof(binnode));

這個語句,在函式體內修改了_tree的內容,將會導致引數tree的內容作相應的修改,因為它們指向相同的記憶體位址。而

_tree = (binnode *) malloc(sizeof(binnode));

這個句,系統重新分配記憶體給_tree指標,_tree指標指向了系統分配的新位址,函式體內修改的只是_tree的內容,對原tree所指的位址的內容沒有任何影響。因此,函式的引數是乙個指標時,不要在函式體內部改變指標所指的位址,那樣毫無作用,需要修改的只能是指標所指向的內容。即應當把指標當作常量。

如果非要使用函式指標來申請記憶體空間,那麼需要使用指向指標的指標

createnode(binnode **tree,char *p)

上面的是林銳的說法,目前來說不知道怎麼去理解,不過可以有另外的方案,通過函式返回值傳遞動態記憶體:

binnode *createnode()

這個倒還說得過去,因為函式返回的是乙個位址的值,該位址就是申請的記憶體塊首位址。但是,這個容易和另外的乙個忠告相混繞

[不要用return語句返回指向「棧記憶體」的指標,因為該內存在函式結束時自動消亡]

這裡區分一下靜態記憶體,棧記憶體和動態分配的記憶體(堆記憶體)的區別:

(1) 從靜態儲存區域分配。內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在。例如全域性變數,static變數。

(2) 在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。

(3) 從堆上分配,亦稱動態記憶體分配。程式在執行的時候用malloc或new申請任意多少的記憶體,程式設計師自己負責在何時用free或delete釋放記憶體。動態記憶體的生存期由我們決定,使用非常靈活,但問題也最多。

因此,試圖返回乙個棧上分配的記憶體將會引發未知錯誤

char *getstring(void)

p是在棧上分配的記憶體,函式結束後將會自動釋放,p指向的記憶體區域內容不是"hello world",而是未知的內容。

如果是返回靜態儲存的記憶體呢:

char *getstring(void)

這裡「hello world」是常量字串,位於靜態儲存區,它在程式生命期內恆定不變。無論什麼時候呼叫getstring,它返回的始終是同乙個「唯讀」的記憶體塊。

指標作為函式引數

當指標作為函式引數時,對引數本身的修改並不影響原來的值,比如下面的 刪除鍊錶中第乙個值為item的結點。但是結果卻不正確。void delete node head,int item 這段 的問題是,第乙個引數是指標型別而head null修改的實際上是這個指標的乙個副本,所以不會對原來的指標產生效...

指標作為函式引數

臨近畢業,還有找工作的事情,繁忙之際還是堅持看一下c語言的知識,重點的地方或者不清楚的地方還是要記錄一下。本章以指標作為函式傳參來說一下學習心得,大部分內容源自c語言程式設計課本。首先從c語言中函式引數的傳遞方向說起,大家都知道,c語言中函式引數的傳遞方向是單向的,只能由主調函式的實參傳遞到被調函式...

指標作為引數傳遞

如果想通過函式呼叫得到n個要改變的值,可以採取下面的步驟 在主調函式中設n個變數,用n個指標變數指向它們 編寫被呼叫函式,其形參為n個指標變數,這些形參指標變數應當與主調函式中的n個指標變數具有相同的基型別 在主調函式中將n個指標變數作實參,將它們的值 是位址值 傳給所呼叫函式的n個形參指標變數,這...