Posted on November 20th, 2007 at 3:28 by fr3@K
我知道很多人一直是這樣做的, 可是我從沒搞懂為什麼在 windows 平台上, 用上了 _TCHAR, _TEXT 再 define 個 _UNICODE. 或是用上了 whar_t 與 std::wstring. 就能算是 Unicode 化的程式?
Unicode 說穿了就是一種 數字到字元的對應. 而 UTF-8/UTF-16/UTF-32 等則是 Unicode 這種數字的編碼方式, 也就是同一個 (能對應 Unicode 字元的) 數字在不同的編碼下會是不同的 byte sequence.
在 WIN32 平台上, wchar_t 是個 16-bits 的型別.1 很明顯地, 它最多只能 (事實上應該也是) 對應到 Unicode 中的 UTF-16 編碼.
UTF-16 定義了約十一萬個字元.2 Wikipedia 也提到 UTF-16 是一種可變長度的編碼. 由此可見, 一個 WIN32 下的 whar_t 沒有辦法總是以一個 16-bits (最大值為 2^16 -1, 也就是 65535) 的數字來代表十一萬種字元.
由此可以知道一個 WIN32 的 wchar_t 是無法完全對應到一個 UTF-32 的 Unicode 字元. 所以類似下面的操作:
utf_32_char_t get_utf_32_char(const std::wstring& wstr, size_t n)
{
assert(wstr.size() > n);
return wstr[n];
}
並無法正確的對應到位於 n 位置的 Unicode 字元. 程式還是必須從 wstr 的頭掃描到第 n 個 Unicode 才能正確將一個 UTF-16 編碼的字元轉為 UTF-32 的字元. Windows 的 wchar_t 的優點或用處到底在那裡?
我看來是這只是偷懶的行為, 假裝每一個 WIN32 的 wchar_t 可以代表任意一個 UTF-16 的字元. 跟鴕鳥把頭躲進沙坑逃避現實的的行為沒什麼差異.
PS. 我對 Unicode 沒有特別研究, 上面應該有很多 Unicode 術語都用錯了. 但 concept 應該沒問題.
[Update: Nov 20, 2007 at 14:40]
感謝 Jeff 在回應裏面提到 Windows 的 wchar_t 是對應到 UCS-2, 而不是 UTF-16.3 這下子我可能有點搞懂了. UCS-2 的確就只能表達 Basic Multilingual Plane (BMP), 也就是 Unicode 中的 0×0000~0xFFFF. 以一個 16-bits 的整數是來表達 BMP 是 just make.
無法表達超出 BMP 的 Unicode, 這是 WIN32 的先天限制? 所謂的 Unicode API 也不真的那麼 Unicode, 是嗎?
好吧, 如果永遠活在 WIN32 的世界下這樣似乎也可行. 可是如果是從別的地方 (譬如透過網路) 傳過來一個非 BMP 的 Unicode 的字元時怎麼辦? 下面的 code 該怎麼寫?
wchar_t utf8_to_ucs2(const char* utf8)
{
if(is_bmp(utf8) == true)
{
wchar_t usc2;
// fine here, we just need an algorithm to transcode
// a UTF-8 encoded BMP code point (character) to UCS-2
return usc2;
}
else
{
// what goes here?
// what to do if the code point is not a BMP?
}
}
[Update: Sep 3, 2008 at 13:40]
Follow up is available in a more recent post - More on Unicoding.
- Default 似乎還不是 built-in/primitive, 而是個 得 include stddef.h/stdlib.h 或… 的 typedef [↩]
- 另外在 rfc2781 的 Section 2 也說明了 UTF-16 無法表示值大於 0×10FFFF 的 Unicode [↩]
- What is the difference between UCS-2 and UTF-16? [↩]
![]() |
|
| Previous Post « 忙茫盲? « |
Next Post » 拒絕 Singleton » |








wchar_t是「fixed size」,不同平台的大小不同。如win32是UCS2-LE,長2 bytes,而UNIX通常是UCS4,長4 bytes。所以,get_utf_32_char()是不會有問題的。
Comment by jeffhung — November 20, 2007 @ 12:30