閱讀860 返回首頁    go 阿裏雲 go 技術社區[雲棲]


函數返回類型為指針類型的一些問題

轉自:https://blog.csdn.net/tigerjb/article/details/7425571


1.

#include<stdio.h>
char  *returnStr()
{
           char  *p = “tigerjibo”;
           return  p;
}
int  main()
{
           char*str;
           str =returnStr();
   //str[0]=’T’;則會引起錯誤,不能修改隻讀數據段中的內容
           printf(“%s\n”,str);
           return0;
}

來分析下該程序。

(1)char  *p = “tigerjibo”。係統在棧上分配四個字節的空間存放p的數值。“tigerjibo”是字符常量,存放在隻讀數據段內。指向完後,係統把”tigerjibo”的地址賦值給p。

(2)函數用return 把p的數值返回。該數值指向隻讀數據段(該數據段內的數據是靜態的不會改變)。退出子函數後,係統把p的數值銷毀。但是p的數值已經通過return 返回。且隻讀數據段中的內容不會被修改和回收(其輸於靜態區域)

(3)在主程序中把該地址又給了str。因此str指向了“tigerjbo”。

(4)該程序雖然能運行,擔又一個缺點,就是在程序中不能修改字符常常量中的數值。如果修改會引起段錯誤。


2. 


#include<stdio.h>
char *returnStr()
{
           char  p[]=”tigerjibo”;
           return  p;
}
int  main()
{
           char  *str;
           str =returStr();
           printf(“%s\n”,str);
}

編譯該程序後,係統會提示如下警告:

function returns  address of local variable

(函數返回一個可變地址)

分析該錯誤:

1>”tigerjibo”是一個字符常量,存放在隻讀數據段中,是不能被修改的。

2>char p[],是一個局部變量,當函數被調用時,在棧上開辟一個空間來存放數組P的內容。

3>char p[]=”tigerjibo”,該語句是把”tigerjibo”的值賦值給數值P,存放在數組p地址處。而不是把”tigerjibo”的地址賦值給數組p。因此,“tigerjibo”此時在係統中有一處備份,一個在隻讀數據段中(不能修改,內容也不會被回收),一個在棧上存儲(可以修改起內容,但函數退出後,其棧上存儲的內容也會被回收)。

4>因此,當return p,返回了數組的首地址,但是當函數退出後,其棧上的內容也將被丟棄,局部變量的內存也被清空了,因此該數組首地址處的內容是一個可變的值。


3.

#include<stdio.h>
char *returnStr()
{
           static  char p[]=”tigerjibo”;
           return  p;
}
int  main()
{
           char  *str;
           str =returnStr();
           str[0]=’T’;
           printf(“%s\n”,str);
}

此程序運行正確。

分析如下:

1>”tigerjibo”是一個字符常量,存放在隻讀數據段中,是不能被修改的。

2>static char p[],是一個靜態局部變量,在讀寫數據段中開辟一個空間給p用來存放其數值。

3>static char p[]=”tigerjibo”,該語句是把”tigerjibo”的值賦值給數值P,存放在數組p地址處。而不是把”tigerjibo”的地址賦值給數組p。因此,“tigerjibo”此時在係統中有一處備份,一個在隻讀數據段中(不能修改,內容也不會被回收),一個在讀寫數據段中存儲(可以修改其內容,當函數退出後,因其在讀寫數據段中存儲,起內容不會被丟棄)。

4>因此,當return p,返回了數組的首地址,但是當函數退出後,雖然棧上的內容都清除了,但是p地址是讀寫數據段中的地址,其上的內容不會被回收。


4.

#include<stdio.h>
#include<string.h>
#include<strdlib.h>
void getmemory(char *p)
{
        p = (char *)malloc(100);
}
int  main()
{
      char  *str=NULL;
      getmemory(str);
      strcpy(str,”helloworld”);
      printf(“%s\n”,str);
}

編譯後錯誤:

段錯誤

分析:在主程序中,str地址為空。在函數傳遞中將str的地址傳給了子函數中的指針p(是拷貝了一份),然後在字函數中給p在堆上申請了一個100字節的空間,並把首地址賦值給p。但是函數傳遞中,p值改變不會影響到主函數中str的值。因此,str的地址仍為空。在strcpy中引用空指針會出現段錯誤。



最後更新:2017-04-03 16:48:34

  上一篇:go 生活記錄博客(on Github)
  下一篇:go Java實現遞歸經典案例——三角數字的多種實現方式