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

C++ 字符串完全指引(一):Win32 字符編碼基礎與 TCHAR 機制

     編輯:關於C++

前言

面對 TCHAR、std::string、BSTR、_tcs 宏等繁雜字符串類型,本指引總結其由來、用法及相互轉換方法。第一部分介紹三種字符編碼模式,理解它們是掌握字符串類型關系的基石。

字符基礎:ASCII、DBCS、Unicode

所有 string 類基於 C 風格字符串(字符數組)。三種編碼模式對應三種字符類型:

  1. SBCS(單字節字符集): 每字符佔 1 字節。ASCII 屬此類。以單字節 0 結尾。
  2. MBCS/DBCS(多/雙字節字符集): 混合 1 字節與 2 字節字符。Windows 採用 DBCS:特定「前導位元組」標識雙字節字符(如 Shift-JIS 中 0x81-0x9F, 0xE0-0xFC),後跟「後續位元組」。以單字節 0 結尾。
  3. Unicode: 所有字符固定 2 字節(寬字符)。以雙字節 0 (0x0000) 結尾。Unicode 不是 MBCS(後者字符長度可變)。

單字節字符含拉丁字母等;雙字節用於東亞/中東語言;Unicode 用於 COM 及 Windows NT 內部。

代碼表示:wchar_t wch = L'1'; wchar_t* wsz = L"Hello";

內存存儲形式對比

SBCS "Bob": 42 6F 62 00

Unicode L"Bob": 42 00 6F 00 62 00 00 00 (小端序)

DBCS "日本語": 93 FA 96 7B 8C EA 00 (每字符 2 字節,前導位元組 > 0x7F)

DBCS存儲 DBCS存儲 DBCS存儲

注意:DBCS 中雙字節字符不可視為 WORD 整體,必須按字節序解讀。

字符串處理函數選擇

  • str* 族:僅用於 SBCS。
  • wcs* 族:僅用於 Unicode。
  • _mbs* 族:微軟 CRT 擴展,支援 DBCS,兼容 SBCS。若軟體可能在 DBCS 國家(中、日、韓)安裝,應優先用 _mbs* 函數。

誤用示例:Unicode 字符串傳給 strlen 會因遇到中間 0 字節而截斷;傳給 wcslen 會越界讀取直到雙零或 GPF。

正確遍歷與索引 DBCS 字符串

SBCS/Unicode 可用指針 ++/-- 或下標,因字符定長。DBCS 嚴禁:

  1. 前向遍歷勿用 ++,除非每次檢查前導位元組。
  2. 絕不使用 -- 後向遍歷。

反例:檢查路徑尾部反斜槓,用 pLastChar-- 會誤讀後續位元組 0x5C('\' 的值)為單字符,導致邏輯錯誤。正確做法用 CharPrev API 後退一個字符(可能 2 字節)。

// 錯誤
char* pLastChar = strchr(szPath, '\0'); pLastChar--;
if (*pLastChar != '\\') strcat(szPath, "\\");

// 正確
char* pLastChar = _mbschr(szPath, '\0');
pLastChar = CharPrev(szPath, pLastChar); // 後退一個字符
if (*pLastChar != '\\') _mbscat(szPath, "\\");

索引規則:勿用減法得索引(如 &arr[strlen(arr)-1] 同理錯誤)。

Win32 API 的雙版本機制與 TCHAR

所有字符串相關 API/消息均有 A (MBCS) 和 W (Unicode) 兩版本,如 SetWindowTextA/W。頭文件用宏映射:

#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif

預設 MBCS 建構(未定義 UNICODE)。若改用 Unicode,需刪 _MBCS、加 UNICODE/_UNICODE,但原 char 變量會類型不匹配。

TCHAR 完美解決跨編碼編譯

#ifdef UNICODE
typedef wchar_t TCHAR;
#define _T(x) L##x
#else
typedef char TCHAR;
#define _T(x) x
#endif

使用 TCHAR sz[] = _T("text"); 即可同碼碼在 MBCS/Unicode 下編譯。配套通用宏:_tcsrchr (替代 strrchr/_mbsrchr/wcsrchr)、_stprintf、_tfopen 等。完整列表見 MSDN「Generic-Text Routine Mappings」。

常用 typedef 對照表

類型MBCS 構建Unicode 構建
WCHARwchar_twchar_t
LPSTRchar*char*
LPCSTRconst char*const char*
LPWSTRwchar_t*wchar_t*
LPCWSTRconst wchar_t*const wchar_t*
TCHARcharwchar_t
LPTSTRTCHAR*TCHAR*
LPCTSTRconst TCHAR*const TCHAR*

何時選擇 Unicode 構建

  1. 程序僅運行於 Windows NT 系統(內部 Unicode,避免轉換開銷,提速)。
  2. 需處理超過 MAX_PATH (260) 限制的長文件名(Unicode API 支援)。
  3. 需使用僅提供 Unicode 版的 API(如 XP 引入的 SetWindowTheme)。

Windows 9x 大多無 Unicode API 實現,故需跑 9x 必用 MBCS。隨 9x 退出歷史舞台,微軟逐漸拋棄 MBCS API。即使當前用 MBCS,也應用 TCHAR 及相關宏,為將來遷移 Unicode 鋪路,同時正確處理 DBCS。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved