首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

Windows 字符集編程:Unicode、DBCS、MBCS 與 TCHAR 模型完全指南

     編輯:VC 教學

字符集演進與核心概念

為何選擇 Unicode?

  1. 全球化:單一二進制支持所有語言,無代碼頁切換痛苦。
  2. 系統原生:Windows NT 內核 (2000/XP/7/10/11) 基於 UTF-16 開發。ANSI API 實為薄層轉換 (內部調用 MultiByteToWideChar/WideCharToMultiByte),有性能/內存開銷。
  3. COM/CLR 強制:COM 接口 `BSTR`、.NET `String` 均為 UTF-16。
  4. 現代標準:Windows CE 僅支持 Unicode;Win9x 系列已退役。

Visual C++ Unicode 編程模型:TCHAR 通用映射

通過定義兩個宏實現同一源碼雙模式編譯:

  • UNICODE:控制 Windows SDK 头文件 (windows.h 等)
  • _UNICODE:控制 C 運行時头文件 (tchar.h, 等)

通常在項目屬性「字符集」設置為「使用 Unicode 字符集」,自動定義兩者。

核心類型映射表

術語全稱特點
SBCSSingle-Byte Character Set單字節 (ASCII, ISO-8859-1),1字節=1字符
DBCSDouble-Byte Character Set雙字節 (中日韓舊編碼: GBK, Shift_JIS, Big5, EUC-KR),ASCII兼容,首字節標識雙字節
MBCSMulti-Byte Character Set多字節統稱 (含DBCS, UTF-8),字符長度可變
UnicodeUniversal Character Set固定碼位 (UTF-16: 2/4字節; UTF-8: 1-4字節; UTF-32: 4字節),覆蓋全球字符

關鍵編程實踐

1. 字符串長度:字符數 vs 字節數

TCHAR str[] = _T("中文abc");
// Unicode: wcslen=6, sizeof=14字節 (含結尾\0)
// ANSI (DBCS): _tcslen=6, strlen=8字節 (中文2字節)
int charCount = _tcslen(str);      // 正確字符數
int byteSize = sizeof(str);        // 數組字節數
int byteLen = _tcslen(str)*sizeof(TCHAR); // 字符串內容字節數

2. DBCS 字符串安全遍歷 (僅 ANSI/DBCS 模式需手動)

Unicode 模式下 wchar_t 固定 2 字節,直接下標訪問安全。ANSI/DBCS 下必須用 API:

  • CharNext(lpsz):返回下一字符指針
  • CharPrev(lpszStart, lpszCurrent):返回上一字符指針
  • IsDBCSLeadByte(b):判斷是否為雙字節首字節
// 正確遍歷 DBCS 字符串
for (LPCTSTR p = str; *p; p = CharNext(p)) {
    // 處理字符 *p (可能是雙字節)
}

3. 字符集轉換

// ANSI (當前代碼頁) -> Unicode
int wlen = MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, NULL, 0);
wchar_t* wstr = new wchar_t[wlen];
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wstr, wlen);

// Unicode -> ANSI
int alen = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
char* astr = new char[alen];
WideCharToMultiByte(CP_ACP, 0, wstr, -1, astr, alen, NULL, NULL);

// 指定代碼頁 (如 UTF-8: CP_UTF8, GBK: 936, Big5: 950)
MultiByteToWideChar(CP_UTF8, 0, utf8Str, -1, wstr, wlen);

4. 文件 I/O 與 Unicode

  • 文件名:CreateFile(_T("中文.txt"), ...) (TCHAR 版本自動調用 CreateFileW)
  • 文件內容:建議統一寫入 UTF-8 (帶 BOM) 或 UTF-16LE。打開文件後用 MultiByteToWideChar/WideCharToMultiByte 轉換內存表示。

5. 常見陷阱

  • 字面量未加 _T():MessageBox(NULL, "中文", ...) Unicode 編譯報錯/亂碼。必須 _T("中文") 或 L"中文"。
  • sizeof 陷阱:sizeof(TCHAR) 編譯期常量 (1或2),sizeof(str) 數組字節數,strlen(str) 僅適用 ANSI。
  • API 混用:lstrlen (TCHAR) vs strlen (char) vs wcslen (wchar_t);wsprintf (TCHAR) vs sprintf/swprintf。
  • 結構體對齊:包含字符串指針的結構體在 ANSI/Unicode 下大小不同,跨模塊傳遞需固定字符集或顯式聲明。

現代建議 (C++17/20, Windows 10/11)

  1. 內部統一 UTF-8 (std::string/u8string):跨平台、標準庫友好、網絡/文件傳輸標準。Windows API 邊界處轉 UTF-16 (MultiByteToWideChar(CP_UTF8...))。
  2. 棄用 TCHAR 模型:顯式使用 wchar_t/LPWSTR 調用 Windows API (W 版本),內部用 std::u8string/std::string (UTF-8) 或 std::u16string。
  3. 字面量用 u8"":u8"中文" (UTF-8), L"中文" (UTF-16), u"中文" (UTF-16 char16_t)。
  4. ICU / std::text (C++26):複雜文本處理 (斷詞、排序、正規化) 用成熟庫。

總結

理解 SBCS/DBCS/MBCS/Unicode 本質、TCHAR 映射機制、系統原生 Unicode (UTF-16) 與 現代 UTF-8 內部表示 的關系,是 Windows 程序員處理文本不亂碼、不崩潰、高性能的核心功力。新項目請擁抱 UTF-8 內部 + 邊界轉 UTF-16 的最佳實踐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
通用類型ANSI (未定義宏)Unicode (定義宏)說明
TCHARcharwchar_t字符類型
PTSTR / LPTSTRLPSTRLPWSTR可修改字符串指針
PCTSTR / LPCTSTRLPCSTRLPCWSTR常量字符串指針
_tcslenstrlenwcslen字符串長度 (字符數)
_tcscpystrcpywcscpy複製
_tcscmpstrcmpwcscmp比較
_tprintfprintfwprintf格式化輸出
_T("text") / TEXT("text")"text"L"text"字符串字面量 (關鍵!)