C語言中函數返回字符串的4中方法
- 函數的構成部分:返回類型、函數名稱、參數、函數主體
- 參數:函數調用時傳入的參數稱為實參,函數定義時出現的參數為形參
- 形參的作用在於接收實參傳入的值,形參和函數內部的其他局部變量相同,在進入函數創建,退出函數銷毀
- 值傳遞:實參的實際值復制給形式參數。修改形參不會改變實際參數
- 引用傳遞:指針傳遞,將實參地址復制給形參,修改形參指向的值時,實參也會發生改變
- 由此,可以得知無論是形式結合還是return語句返回時,都存在一個拷貝的過程。值傳遞的過程是將這個值拷貝一份在函數內部使用,引用傳遞的過程是將地址拷貝一份使用。同樣在return返回時,返回一個值,函數會將該值拷貝一份供主函數使用,返回指針,自然拷貝的就是一個地址,供主函數使用。
- 下面是一個錯誤示例
-
#include <stdio.h> #include <string.h> char * retstring(); int main() { char * name2; name2 = retstring(); printf("%s\n",name2); return 0; } char * retstring() { char name[10]; strcpy(name,"漢青"); return name; } - 上面這段代碼會出現一個警告,這是因為返回了一個局部變量name的地址。在主函數中該局部變量name時處於銷毀狀態,所以name內存空間還沒有被重寫的話主函數中name2的值是正確,如果被其他程序重寫,就會出現未知異常。
- 所以返回局部變量的字符串時很可怕的
- 函數返回字符串的方法:
- 將字符串指針作為函數參數傳入,並返回該指針
- 使用malloc函數動態分配內存,在主調函數中釋放
- 返回一個靜態局部變量
- 使用全局變量
將字符串指針作為函數參數傳入,並返回
- 典型的strcpy函數應該采用的就是這種方法:
-
char* strcpy(char* des,const char* source) { char* r=des; assert((des != NULL) && (source != NULL)); while((*r++ = *source++)!='\0'); return des; }
-
使用malloc函數動態分配內存,但是一定要注意在主調函數中將其釋放,因為malloc動態分配的內存位於堆區,而堆區的內存是需要自己釋放的###
-
#include <stdio.h> #include <string.h> #include <stdlib.h> char * retstring(); int main() { char * name2; name2 = retstring(); printf("%s\n",name2); //記住一定要用free釋放,否則會造成內存泄露 free(name2); return 0; } char * retstring() { char * name; name = (char *)malloc(10); strcpy(name,"張漢青"); return name; }
返回一個靜態局部變量
-
#include <stdio.h> #include <string.h> #include <stdlib.h> char * retstring(); int main() { char * name2; name2 = retstring(); printf("%s\n",name2); return 0; } char * retstring() { static char name[10]; strcpy(name,"張漢青"); return name; } - 這種方法在於采用了靜態局部變量(位於靜態區,程序結束時由系統釋放),這會導致,下一次調用會將上次調用產生的結構進行覆蓋。
- 使用這樣的函數應該立即將結構拷貝一份
使用全局變量
-
char g_s[100]; char* fun() { strcpy(g_s, "abc "); return g_s; }
函數返回字符串問題
- 歸根結底,返回字符串就是要返回一個地址,同時需要保證地址在主調函數有效。
- 直接定義char*變量,會保存在棧區,變量的作用域外會被立即銷毀;malloc申請空間保存在堆區,需要手動銷毀;靜態區變量程序結束時銷毀。
- 所以返回一個地址要么擴大他的作用域,要么控制其生命周期。
- 引用自:https://www.cnblogs.com/qingergege/p/6496683.html
