Visual C ++:buggy towupper

时间:2014-02-12 07:58:14

标签: c++ visual-studio gcc unicode

给出以下代码:

#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给出的答案对我来说似乎是正确的,因为0x178(Ÿ)是0xff(ÿ)的正确大写Unicode代码点。

但是,0x9f也是Ÿ的代码点,但在使用的Windows-1252代码页中。因此看起来好像Visual C的towupper将输入视为一个窄字符,并根据预设的代码页解释它。

至于我的理解,宽字符应始终解释为Unicode代码点,Windows / VC上的UTF-16和Linux / gcc上的UTF-32。我错在这里,还是微软实施中的错误?或者只是规范在这种情况下不够严格,两者都可以被视为正确的结果?

1 个答案:

答案 0 :(得分:1)

从对问题的评论来看,似乎没有“真正的”解决方案; C或C ++标准对字符编码的要求不够严格,因此我们无法对区域设置敏感结果抱有真正的期望。

对于我在Windows上的特定用例,虽然它取决于平台,但CharUpperW是一个可行的选择。