2013-05-03 34 views
4

MSDN爲什麼設置了中文代碼頁的Windows控制檯可以顯示UTF-16編碼字符?

「對於Microsoft C/C++編譯器,源和執行字符集都是ASCII」。

C++ 03

2.1翻譯

」的階段.. 在基本源字符的任何源文件字符集 (2.2)是由取代指定 字符的通用字符名稱()實現可以使用任何內部編碼,很長的 作爲源文件中遇到的實際擴展字符,和 相同的擴展字符在源文件中表示爲 通用字符名稱。使用爲\ uXXXX表示法),被處理 等效。)「

2.13.2字符文字

」通用字符名稱被轉換到編碼,在 執行字符集,這個角色的名字。如果不存在這樣的 編碼,通用字符名稱被轉換爲一個 實現定義的編碼」

爲了測試其執行字符集被用於由MSVC++,我寫以下代碼:

wchar_t *str = L"中"; 
unsigned char *p = reinterpret_cast<unsigned char*>(str); 
for (int i = 0; i < sizeof(L"中"); ++i) 
{ 
    printf ("%x ", *(p + i)); 
} 

輸出顯示2d 4e 0 00x4e2d是這個中國字的UTF-16 encoding所以,我的結論:UTF-16作爲由MSVC(我的版本:2012 4.5.50709)設置執行字符

之後,我嘗試將此字符輸出到Windows控制檯。由於控制檯使用的默認語言環境爲"C",因此我將語言環境設置爲代碼頁936,表示簡體中文字符。

// use the execution environment locale setting, which is 936 
wchar_t *str = L"中"; 
char* locale = setlocale(LC_ALL, ""); 
wprintf (L"%ls\n", str); 

,輸出:

我很好奇的是,如何在UTF-16編碼字符由Windows控制檯,其區域(解碼器)解碼設爲非UTF-16(MS代碼第936頁)?這怎麼可能發生?

回答

2

我想我明白了。

在Microsoft C++ 2008(可能2005+),CRT用作wprintfwcout被實現爲使得它們轉換寬字符串文字作爲L"中"在UTF-16進行編碼,在引擎蓋下,以匹配當前區域/代碼頁設置。因此,這裏發生的是L"中"被轉換爲代碼頁936中的簡體中文字節D6 D0

我錯了setlocale設置控制檯代碼頁。它只是設置「轉換」期間CRT功能使用的當前程序代碼頁。對於更改控制檯代碼頁,命令chcp或Win API SetConsoleOputputCP()達到。

由於我的控制檯的默認頁面是936,該字符可以正確顯示沒有問題。

+0

您可以使用調試器並查看內存位置,以確定下面發生了什麼。 – 2013-05-04 09:38:02

0

如何在UTF-16編碼的字符由Windows控制檯,其區域(解碼器)被設爲非UTF-16

有兩種方法,你可以寫文字的解碼安慰。使用Win32 API WriteConsoleA的字節方式爲您提供了使用控制檯代碼頁(「ANSI」)解釋的字節。Unicode方式WriteConsoleW接收一個UTF-16LE字符串,並直接將字符寫入控制檯,而不必擔心它使用的代碼頁。

當輸出爲交互式控制檯時,stdio功能printf使用WriteConsoleA。至少從VS 2005開始的wprintf函數調用WriteConsoleW

+0

如果控制檯使用默認的語言環境「C」,或者使用不同的語言環境,例如「英語」,則「wprintf」不會輸出正確的字符「中」。所以恐怕情況並非如此。 – 2013-05-04 05:04:50

相關問題