字串處理是 C++ 開發的高頻需求。C++ 同時支援 C 風格字串(以 \0 結尾的字元陣列)、原始字元陣列、與現代 std::string 三種形式。本文系統解析三者核心差異、記憶體佈局、常見操作函式、修改語意陷阱,並建立現代 C++ 字串處理最佳實踐。
| 形式 | 範例 | 結尾 | 長度計算 | 修改安全性 | 管理方式 |
|---|---|---|---|---|---|
| C 風格字串 | char s[] = "hello"; | 自動附加 \0 | strlen(s) | 可修改(陣列在堆疊) | 手動/陣列生命週期 |
| 字元陣列 | char s[] = {'h','e','l','l','o'}; | 無 \0(除非手動加) | sizeof(s) | 可修改 | 手動/陣列生命週期 |
| 字串常值 | char *p = "hello"; | 唯讀區含 \0 | strlen(p) | ❌ 修改導致 UB | 靜態儲存期 |
| std::string | string s = "hello"; | 內部管理 | s.size() | ✅ 安全、自動擴充 | RAII 自動管理 |
char a[] = "hello"; // sizeof=6 (含\0), strlen=5
char b[] = {'h','e','l','l','o'}; // sizeof=5, strlen=未定義(無\0)
char b2[] = {'h','e','l','l','o','\0'}; // sizeof=6, strlen=5
char s[] = "abc";
char *p = "abc";
s[0] = 'x'; // ✅ 合法:陣列在堆疊,可修改
// p[0] = 'x'; // ❌ 非法:p 指向唯讀常數區
關鍵:陣列名非執行期實體,編譯期分配空間;指標為執行期變數,指向唯讀區導致修改崩潰。
char *p = "abc";
char *q = p; // 淺複製:同指向唯讀區
string s1 = "abc";
string s2 = s1; // 深複製:獨立緩衝區,修改互不影響
strcpy(dst, src)、strncpy:複製strcat(dst, src)、strncat:串接strlen(s):長度(不含 \0)strcmp(s1, s2):比較strlwr/strupr:大小寫轉換(非標準)std::string:自動記憶體管理、邊界檢查、SSO(短字串優化)、豐富介面str.c_str() 取得 const char*,str.data() 取得非 const 緩衝區(C++17)\0 遺漏、淺複製是主要 Bug 來源std::format (C++20)、fmt::format、ostringstream 替代 sprintfstd::string_view (C++17) 避免不必要複製理解 C 風格字串、字元陣列、字串常值、std::string 的記憶體佈局、修改語意、複製行為差異,是避免緩衝區溢位、懸空指標、資源洩漏的基礎。現代 C++ 專案應全面採用 std::string/string_view,將 C 風格字串限制在介接舊代碼/系統 API 的邊界層。