5

注意:我问的是 Microsoft Visual C++ 2008 上的实现定义的行为(可能与 2005+ 相同)。操作系统:Win7简体中文安装。

当我使用 执行非 ASCII I/O 时,我感到很惊讶printf。例如

   // This won't be necessary as it's the system default code page.
   //system("chcp 936");
   
   // NULL to show current locale, which is "C"
   printf ("%s\n", setlocale(LC_ALL, NULL));
   printf ("中\n");
   printf ("%s\n", setlocale(LC_ALL, "English"));
   printf ("中\n");

输出:

Active code page: 936
C
中
English_United States.1252
?D

调试器中的内存占用显示它"中"以两个字节编码:0xD6, 0xD0,这是代码页 936 中该字符的代码点,用于简体中文。它不应该在最有可能是的代码点范围"C" locale内。0x0 ~ 0x7F

问题:

为什么它仍然可以在“C”语言环境中正确显示字符?所以我猜测语言环境与此无关printf"English"但是,我会问,为什么切换到与 936 不同的 locale时就不能显示了?有趣的?

编辑:

我将标准输出重定向到一个文件并进行了一些测试。它表明无论设置什么语言环境,正确的字符"中"都会保存在文件中。它表明这setlocale()与控制台显示字符的方式有关,这与我对其工作原理的理解相矛盾:printf将字节/代码点放入控制台的输入缓冲区,控制台使用自己的代码页(chcp返回的内容)解释这些字节。

4

3 回答 3

3

936 是相当棘手的代码页,它允许 2 个符号字符(类似于 UTF-8 所做的)。例如 Cyrillic (866) - 不允许使用两字节字符,它的行为将与“English”相同。

因此,当您使用 default(936) 代码页时,它知道如何处理 2 符号字符,而“English”0x0 ~ 0x7f仅处理。

让我也回答为什么wprintf(L"中")失败。控制台应用程序和 Windows 窗口应用程序之间有很大的不同,它们使用不同的代码页以下是控制台和窗口之间的匹配:

DOS   |   Windows
------+----------
850   |  1252
936   | 54936
866   |  1251

因此,如果您想在控制台中看到正确的符号WideCharToMultiByte,请先使用 - 它提供了预期的转换以允许控制台在 936 中工作

于 2013-05-06T08:36:30.230 回答
3

C 语言环境完全按照给定的方式打印出字符串这一事实并不奇怪。这就是我所期望的。令人惊讶的是,英语语言环境会做一些不同的事情。

根据MSDN 上的语言环境文档,语言环境应该具有的唯一效果printf是确定数值的基数字符(即小数点)。

我怀疑这可能是微软编译器中的一个错误。或者至少它是无证行为。

对于它的价值,在我的编译器(Borland)上,语言环境对这些字符串的输出没有影响。它确实会影响基数。

于 2013-05-07T17:05:39.420 回答
0
于 2013-05-17T00:05:24.093 回答