考慮下面的代碼:的Visual C++:越野車towupper
#include <iostream>
#include <cwctype>
#include <clocale>
int main()
{
wchar_t c = L'\u00ff'; // ÿ LATIN SMALL LETTER Y WITH DIAERESIS
// → 0178 Ÿ latin capital letter y with diaeresis
std::cout << std::hex << std::showbase;
#ifdef WIN32
const char * lcc = setlocale(LC_ALL, "English");
#else
const char * lcc = std::setlocale(LC_ALL, "en_US.cp1252");
#endif
if(lcc) {
std::cout << "set locale: " << lcc << std::endl;
std::cout << "towupper(" << (std::wint_t)c << ") = " << towupper(c) << '\n';
} else {
std::cout << "failed to set locale" << std::endl;
}
}
如果我編譯並在Visual Studio 2010(也2013)運行它,結果是:
set locale: English_United States.1252
towupper(0xff) = 0x9f
在Linux上用gcc :
set locale: en_US.cp1252
towupper(0xff) = 0x178
towupper的結果在兩個平臺上是不同的,linux/gcc給出的答案似乎對我來說是正確的,因爲t他0x178(Ÿ)是0xff(ÿ)的正確大寫Unicode代碼點。
但是,0x9f也是Ÿ的代碼點,但在使用的Windows-1252代碼頁中。因此,看起來好像Visual C的towupper會將輸入視爲一個窄字符,並根據預設的代碼頁進行解釋。
至於我的理解,寬字符應該總是被解釋爲Unicode代碼點,Windows/VC上的UTF-16和Linux/gcc上的UTF-32。我在這裏錯了嗎,還是在Microsoft實施中真的是一個錯誤?或者只是在這種情況下規格不夠嚴格,而且都可以被視爲正確的結果?
您明確地將您的區域設置爲CP1252,它是一個8位編碼。如果有的話,我會說異常版本是Linux版本,因爲在0xff之後應該沒有可用的字符(並且在wstring中每個字符至少會浪費1個字節)。 –
MSVC CRT的記錄行爲:「towupper的大小寫轉換是特定於locale的」。對於Linux:「這個函數不適合處理Unicode字符」。 –
@ user846250據我所知,towupper應該將輸入視爲一個Unicode代碼點,因此不會根據任何代碼頁來解釋它。所以語言環境的代碼頁設置應該是不相關的。有一個toupper變體(沒有'w')應該根據代碼頁來解釋輸入。 –