C 語言中「函數返回局部數組/變量指針」是經典錯誤。本文通過整數轉字符串函數實例,深度剖析棧幀銷毀導致內容被覆蓋的機制,並給出三種正確解法。
char* swich(int n) {
char A[20], B[20]; // 局部數組在棧上
char *p = B;
// ... 轉換邏輯填充 B ...
printf("%s,", p); // 函數內輸出正常:234
return p; // 返回棧地址!
}
void main() {
char *p = swich(-234);
char b[10];
strcpy(b, p); // 複製亂碼
printf("%s,", b); // 輸出亂碼
// 單字符訪問 p[0]='2' 正常,p[1]、p[2] 亂碼
}
swich 執行時,A、B、p 分配在棧幀中printf 先計算參數 p(地址值)壓棧,此時 B 內容完好printf 執行需建立自身棧幀,**覆蓋**了 swich 的棧空間(包括 B)swich 返回,其棧幀正式銷毀,內存標記為可用main 中後續操作(strcpy、再次 printf)讀取已失效地址,內容已被破壞關鍵點:第一次 printf 能輸出正確是因參數求值在 printf 執行**前**完成,但後續任何訪問均屬未定義行為。
void swich(int n, char *buf, size_t size) {
// 直接寫入調用者提供的緩衝區
// 需檢查 size 防止溢出
}
void main() {
char buf[20];
swich(-234, buf, sizeof(buf));
printf("%s\n", buf);
}
char* swich(int n) {
static char B[20]; // 靜態存儲區,生命周期全程
// ... 填充 B ...
return B;
}
char* swich(int n) {
char *p = malloc(20); // 堆內存,手動管理
// ... 填充 p ...
return p;
}
void main() {
char *p = swich(-234);
printf("%s\n", p);
free(p); // 必須釋放
}
首字符 '2' 可能恰好未被後續棧操作覆蓋,但相鄰字節已被修改。這是巧合,**不可依賴**。
-Wreturn-local-addr 會警告:function returns address of local variable這個「經典錯誤」看似簡單,實則觸及 C 語言內存模型核心,是區分初學者與資深工程師的分水嶺。