为什么ANSI代码页和控制台代码页有所不同?

时间:2017-04-03 15:59:03

标签: windows visual-studio visual-studio-2015 windows-console codepages

Microsoft Windows提供了几种查询当前代码页的功能: GetACPGetConsoleOutputCPGetConsoleCP

他们返回不同的值。例如,在我的计算机上,GetACP返回1252而GetConsoleOutputCPGetConsoleCP返回437.

(我们也可以在命令行运行chcp并获得437)

  • 为什么Windows为控制台和非控制台提供不同的代码页?
  • 这些代码页如何根据机器确定?
  • 同一台机器上的代码页之间有什么关系?控制台和非控制台代码页之间是否存在关联?具有代码页1252的机器是否总是具有437的控制台代码页?

此问题的背景是来自Visual Studio C ++的错误消息:

error C2855: command-line option '/source-charset' inconsistent with precompiled header
error C2855: command-line option '/execution-charset' inconsistent with precompiled header

当预编译头文件使用与使用它们的CPP文件不同的默认代码页(无论出于何种原因)构建时,会发生这些错误。
来自MSDN docs

  

如果未找到字节顺序标记,则假定源文件已编码   除非您指定字符集,否则使用当前用户代码页   使用/ source-charset选项命名或代码页。

所以我试图找出他们引用的代码页,GetACP或其他代码页返回的代码页......

3 个答案:

答案 0 :(得分:8)

ANSI和OEM代码页由系统引导时加载的系统区域设置决定。它们作为PEB字段AnsiCodePageDataOemCodePageData映射到每个流程。 ntdll.dll中的运行时库有许多适用于这些字符串类型的函数,例如RtlAnsiStringToUnicodeStringRtlOemStringToUnicodeString

Windows API中以A结尾的函数是ANSI,但文件系统函数可以通过SetFileApisToOEM切换到OEM。控制台API默认为OEM以与旧版应用程序兼容,并可通过SetConsoleCPSetConsoleOutputCP更改为其他代码页。 chcp.com(或mode.com)调用这些函数,但不允许将输入缓冲区和屏幕缓冲区设置为不同的代码页。

如果ANSI代码页是1252,则OEM代码页不一定是437.这仅在美国语言环境中。使用1252作为ANSI代码页的大多数西方语言环境将使用850作为OEM代码页。

表示使用用户代码页的应用程序可能不是指系统ANSI或OEM代码页。相反,它可以调用,例如GetLocaleInfoEx来查询LOCALE_NAME_USER_DEFAULTLOCALE_IDEFAULTANSICODEPAGE的{​​{1}}区域设置。

答案 1 :(得分:2)

由于遗留原因,命令控制台使用不同的代码页。在控制台上运行的程序通常是为DOS编写的,字符集包括在此上下文中有用的线条图字符等内容。在具有本机Windows应用程序的图形环境中,扩展可用字符更为重要,因为直接绘制线条而不是用字体模拟。

默认代码页由Windows将使用的语言决定。不同的语言需要不同的字符,单个代码页不足以适合欧洲语言使用的所有字符。例如,您会在某些中欧和东欧地区使用code page 1250

答案 2 :(得分:0)

  

每台机器如何确定这些代码页?

查看此表National Language Support (NLS) API Reference

或查询您的注册表:

C:\>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v OEMCP

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage
    OEMCP    REG_SZ    850


C:\>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v ACP

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage
    ACP    REG_SZ    1252