字串反轉是經典面試題。本文提供兩種標準實現——**指標雙向交換**(需動態分配)與**陣列原地交換**——並深度講解 malloc/free 堆記憶體管理、棧/堆區別、野指針防範,建立正確的記憶體操作肌肉記憶。
#include
#include
#include
int main() {
const char *src = "hello world";
int len = strlen(src);
// 1. 分配目標緩衝區(含結束符)
char *dest = (char*)malloc(len + 1);
if (!dest) return 1; // 分配失敗檢查
char *d = dest;
const char *s = &src[len - 1]; // 指向最後一個有效字元
// 2. 反向複製
while (len-- > 0) *d++ = *s--;
*d = '\0'; // 手動添加結束符(關鍵!)
printf("反轉結果: %s\n", dest); // dlrow olleh
// 3. 釋放並置空(防野指針)
free(dest);
dest = NULL;
return 0;
}
關鍵點:malloc 分配堆記憶體,free 歸還,ptr = NULL 防止懸空指針二次釋放/誤用。
#include
#include
int main() {
char str[] = "Hello world"; // 陣列在棧上,可修改
int len = strlen(str);
char tmp;
for (int i = 0; i < len / 2; i++) {
tmp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = tmp;
}
printf("反轉結果: %s\n", str); // dlrow olleH
return 0;
}
優勢:無動態分配開銷,無記憶體洩漏風險,適合固定緩衝區場景。
| 特性 | 堆 | 棧 |
|---|---|---|
| 管理方式 | 程式設計師手動 malloc/free / new/delete | 編譯器/作業系統自動分配釋放 |
| 空間大小 | 巨大(GB級,受限於虛擬記憶體) | 較小(通常 1~8MB,線程棧) |
| 分配速度 | 較慢(系統呼叫、碎片管理) | 極快(指針遞增/遞減) |
| 生命週期 | 手動控制,跨函數共享 | 隨作用域進出自動管理 |
| 典型用途 | 動態資料結構、大塊緩衝區、跨模組共享 | 區域變數、函數參數、返回地址、臨時緩衝區 |
| C/C++ 對應 | malloc/free, new/delete | 自動變數、alloca (非標準) |