現象代碼
int testA() { int b=1; return b; } // 正常
char *testB() { char str[]="abc"; return str; } // 危險!
返回值(按值返回)
testA 返回 int,編譯器在調用處創建臨時變量接收副本,b 銷毀不影響結果。
- 標量、結構體(C99)按值返回均安全。
返回指針(返回局部數組地址)
str 是棧上數組,函數返回後棧幀銷毀,內容隨時被覆蓋。
- 編譯器創建臨時指針變量接收地址,但指向已失效內存。
- 「僥倖輸出正確」純屬未被覆蓋,極不穩定。
正確替代方案
| 方案 | 代碼 | 適用場景 |
| 靜態局部變量 | static char str[]="abc"; return str; | 單例、只讀字符串 |
| 字符串字面量 | return "abc"; | 只讀常量,存儲在 .rodata |
| 調用者提供緩衝區 | void testB(char *buf, size_t n) { strncpy(buf, "abc", n); } | 線程安全、可重入 |
| 動態分配 | char *p=malloc(4); strcpy(p,"abc"); return p; | 長度動態,調用者負責 free |
| 返回結構體(C99) | struct S { char buf[4]; }; return (struct S){"abc"}; | 小固定長度,按值返回 |
返回引用
不產生副本,效率最高,但嚴禁返回局部變量引用,同樣會懸空。
編譯器警告
現代編譯器(GCC/Clang/MSVC)對返回局部地址會發出 -Wreturn-local-addr 警告,務必開啟並修復。
- 上一篇文章: C語言指針實現兩數交換:標準 swap 函數與 malloc/free 完整演示
- 下一篇文章: C語言 open 系統調用詳解:參數標誌位、權限模式、可變參數原型
Copyright ©
程式碼之家 All Rights Reserved