函數返回類型為指針類型的一些問題
轉自: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地址是讀寫數據段中的地址,其上的內容不會被回收。
#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