指標作為函數形參的思考

來源:互聯網
上載者:User

最近在論壇上看到有一篇文章提問下面的問題: 

char * fun(char *p)
{
      return p;
}
提問:此函數返回的是誰的值,是參數p的地址,還是p的值? 

回答:

p的值,但其值指向一個記憶體位址

p是棧中的地址,和局部變數的地址一樣,函數返回後這塊記憶體就無效了。

這種用法還是很常見的,比如鏈表中。

雖然p是棧中的地址,但是因為它只是指標副本,所以可以改變指標的指向(通過return的傳回值),指向其他地方。

記得在學習C語言函數那部分的時候,有一個很重要的概念是區別:值傳遞、指標傳遞、引用傳遞(好像是這三種說法)。

我覺得要理解這部分知識點,首先應該知道不同種類的變數在記憶體中是如何分配儲存的,它們的生命週期多長等這些問題,然後再看上面的三種情況就好理解了。函數的參數都是在stack棧上分配的,所以它們的生命週期就在它們所屬的函數內,函數執行完畢的時候,它們所佔的記憶體將被回收。

如果我們想在函數內對實參進行操作(不是對實參的副本,形參)的話,一般會使用引用,即聲明函數的形參為參考型別,比如char * fun(char * &p),這樣實參和形參為同一個變數,我們在函數中操作形參p就等於直接在操作實參變數。在看C++文法書的時候,書上說這樣用還有一個好處是,在調用函數的時候,不用再為形參分配記憶體了,所以這樣執行效率會高一點兒。

 

下面是函數形參為指標的幾種情況:

#include <iostream><br />using namespace std;<br />char* func1(char *p);<br />void func2(char *p);<br />void func3(char * &p);<br />char s1[]="原來的";<br />char s2[]="指向我了嗎";<br />int main()<br />{<br /> char *ptr=s1;<br /> cout<<ptr<<endl;<br /> ptr=func1(ptr); //傳回值改變ptr使它指向另一個地址<br />//func2(ptr); //ptr的指向沒有改變,func2函數中改變的只是它的副本(一個局部變數)<br />//func3(ptr); //改變了ptr的指向,func3函數的形式參數為參考型別,實參和形參是同一個變數<br /> cout<<ptr<<endl;<br /> return 0;<br />}<br />char* func1(char *p)<br />{<br /> p=s2;<br /> return p;<br />}<br />void func2(char *p)<br />{<br /> p=s2;<br />}<br />void func3(char * &p)<br />{<br /> p=s2;<br />}

下面再看一個在實際應用中經常會出錯的一個例子(檢測一下我們是否理解了上面的概念):

#include <malloc.h><br />struct stack<br />{<br />char *elem[10];<br />int top;<br />};<br />void initial1(struct stack *s)//值傳遞<br />{<br />s = (stack*)malloc(sizeof(stack));<br />}<br />void initial2(struct stack **s)//指標傳遞<br />{<br />*s = (stack*)malloc(sizeof(stack));<br />}<br />void initial3(struct stack *&s)//引用傳遞<br />{<br />s = (stack*)malloc(sizeof(stack));<br />}<br />int main(int argc, char* argv[])<br />{<br />struct stack *s;<br /> //initial1(s); // error,沒有獲得返回的值<br />initial2(&s); // ok<br />initial3(s); // ok</p><p>return 0;<br />}

下面是某company對此知識點出的考題:

[Q1]<br />void Getmemory(char*p)<br />{<br />p=(char*)malloc(100);<br />}<br />void Test(void)<br />{<br />char *str=NULL;<br />Getmemory(str);<br />strcpy(str,"Hello world");<br />printf(str);<br />}<br />//modified to:<br />#include <stdio.h><br />#include <string><br />void Getmemory(char**p)<br />{<br />*p=(char*)malloc(100*sizeof(char));<br />}<br />void Test()<br />{<br />char *str=NULL;<br />Getmemory(&str);<br />strcpy(str,"Hello world");<br />printf(str);<br />}<br />int main()<br />{<br />Test();<br />return 0;<br />}</p><p>[Q2]<br />char* Getmemory(void)<br />{<br />char p[]="hello world";<br />return p;<br />}<br />void Test(void)<br />{<br />char *str=NULL;<br />str=Getmemory();<br />printf(str);<br />}<br />//modified to:<br />#include <stdio.h><br />char* Getmemory(void)<br />{<br />char p[]="hello world";<br />return p; //returning address of local variable or temporary<br />}<br />void Test()<br />{<br />char *str=NULL;<br />str=Getmemory();<br />printf(str); //unknown results<br />}<br />int main()<br />{<br />Test();<br />return 0;<br />}</p><p>[Q3]<br />void Getmemory(char**p,int num)<br />{<br />*p=(char*)malloc(num);<br />}<br />void Test(void)<br />{<br />char *str=NULL;<br />Getmemory(&str,100);<br />strcpy(str,"Hello world");<br />printf(str);<br />}<br />//modified to:<br />#include <stdio.h><br />#include <string><br />void Getmemory(char**p,int num)<br />{<br />*p=(char*)malloc(num*sizeof(char));<br />}<br />void Test()<br />{<br />char *str=NULL;<br />Getmemory(&str,100);<br />strcpy(str,"Hello world");<br />printf(str); //print "Hello world"<br />}<br />int main()<br />{<br />Test();<br />return 0;<br />}</p><p>[Q4]<br />void Test(void)<br />{<br />char *str=(char*)malloc(100);<br />strcpy(str,"Hello");<br />free(str);<br />if(str!=NULL)<br />strcpy(str,"world");<br />printf(str);<br />}<br />//modified to:<br />#include <stdio.h><br />#include <string><br />void Test()<br />{<br />char *str=(char*)malloc(100*sizeof(char));<br />strcpy(str,"Hello");<br />free(str); // free the contents which str points<br /> //in this place, we'd better set str to NULL otherwise the pointer str will to be a wild pointer<br />if(str!=NULL) //this statement is always true,for str is non-NULL<br />strcpy(str,"world");<br />printf(str); //print "world"<br />}<br />int main()<br />{<br />Test();<br />return 0;<br />}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.