| 語法 | 型別 | 編碼目標 | C11 前綴 |
'a' | int | 執行字符集單位 | — |
L'a' | wchar_t | 寬執行字符集 | — |
u'a' | char16_t | UTF-16 | C11 |
U'a' | char32_t | UTF-32 | C11 |
"abc" | char[] | 執行字符集 | — |
L"abc" | wchar_t[] | 寬執行字符集 | — |
u8"abc" | char[] | UTF-8 | C11 |
u"abc" | char16_t[] | UTF-16 | C11 |
U"abc" | char32_t[] | UTF-32 | C11 |
四、常見編碼問題與解決方案
1. 原始檔編碼 ≠ 編譯器預期
GCC 預設原始碼字符集為 UTF-8。若檔案為 GBK,中文註解/字串會編譯錯誤或產生亂碼。
- 解法:統一專案用 UTF-8 (含 BOM 或無 BOM),編譯器加
-finput-charset=GBK (舊專案遷移)。
- IDE 設定檔案編碼為 UTF-8。
2. 執行字符集不支援所需字符
嵌入式系統執行字符集為 ASCII/ISO-8859-1,無法直接儲存中文。
- 方案:原始碼用 Unicode 碼位
"\u4E2D" 或 U"\u4E2D",執行期由 ICU/libiconv 轉換為目標編碼 (GBK/Big5/UTF-8) 輸出。
3. 字串字面值在不同平台行為不一
// Windows (MSVC) 執行字符集通常為當前代碼頁 (CP936/GBK)
// Linux (GCC) 執行字符集通常為 UTF-8
char *s = "中文";
// sizeof(s) 在 Windows=3 (GBK), Linux=6 (UTF-8) — 可移植性極差!
最佳實踐:明確指定編碼前綴,避免依賴隱含執行字符集。
五、多位元組與寬字元處理實戰
標準庫函數族
mblen, mbtowc, wctomb:單字元轉換 (依賴 setlocale)。
mbstowcs, wcstombs:字串轉換。
printf/scanf 格式:%s (多位元組)、%ls (寬字元)。
跨平台通用策略:內部統一 UTF-8/UTF-32,邊界轉換
// 內部一律用 UTF-8 (char*) 或 UTF-32 (char32_t*)
// 輸入:檔案/網路/使用者輸入 → iconv/ICU → 內部 UTF-8
// 處理:演算法運作於 UTF-8 碼位/字節
// 輸出:內部 UTF-8 → iconv/ICU → 目標編碼 (GBK/UTF-16/JSON \uXXXX)
六、C11/C18 現代特性
u8"..." 明確 UTF-8 字串字面值 (C11)。
char16_t, char32_t, <uchar.h> 固定寬度 Unicode 型別。
u'😀' U'😀' 支援增補平面字符 (C11)。
static_assert 編譯期驗證編碼假設。
七、總結建議
- 專案強制統一 UTF-8 無 BOM 原始檔編碼。
- 編譯器旗標明確指定
-finput-charset=UTF-8 -fexec-charset=UTF-8 (GCC/Clang)。
- 字串字面值優先用
u8"..." 明確 UTF-8,避免隱含執行字符集。
- 內部資料結構採用 UTF-8 或 UTF-32,邊界處理用
iconv / ICU。
- 嵌入式無標準庫環境,手寫 UTF-8 ↔ 目標編碼查表轉換。
- 上一篇文章: C 語言未定義行為完全指南:常見陷阱、後果與避坑策略
- 下一篇文章: 反轉二叉樹演算法詳解:遞迴與迭代兩種 C/C++ 實作
Copyright ©
程式碼之家 All Rights Reserved