Visual Studio 为什么ANSI代码页和控制台代码页不同?

x6h2sr28  于 2023-03-09  发布在  其他
关注(0)|答案(4)|浏览(247)

Microsoft Windows提供了几个用于查询当前代码页的函数:一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个。
它们返回不同的值。例如,在我的计算机上,GetACP返回1252,而GetConsoleOutputCPGetConsoleCP返回437。
(We也可以在命令行上运行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或其他代码页返回的代码页...

pbwdgjma

pbwdgjma1#

ANSI和OEM代码页由系统启动时加载的系统区域设置决定。它们作为PEB字段AnsiCodePageDataOemCodePageDataMap到每个进程。ntdll.dll中的运行时库有许多函数可以处理这些字符串类型,例如RtlAnsiStringToUnicodeStringRtlOemStringToUnicodeString
Windows API中以A结尾的函数是ANSI,但文件系统函数可以通过SetFileApisToOEM切换到OEM。控制台API默认为OEM以与旧应用程序兼容,并且可以通过SetConsoleCPSetConsoleOutputCP更改为其他代码页。chcp.com(或mode.com)调用这些函数,但它不允许将输入缓冲区和屏幕缓冲区设置为不同的codepage。
如果ANSI代码页是1252,则OEM代码页不一定是437。这仅适用于美国区域设置。大多数使用1252作为ANSI代码页的西方区域设置将使用850作为OEM代码页。
一个声称使用用户代码页的应用程序可能不是引用系统ANSI或OEM代码页,而是调用GetLocaleInfoEx来查询LOCALE_NAME_USER_DEFAULT区域设置中的LOCALE_IDEFAULTANSICODEPAGELOCALE_IDEFAULTCODEPAGE

lg40wkob

lg40wkob2#

由于传统的原因,命令控制台使用不同的代码页。在控制台上运行的程序通常是为DOS编写的,字符集包括在这种情况下有用的画线字符。在带有本机Windows应用程序的图形环境中,扩展可用字符更为重要,因为线条将直接绘制,而不是用字体模拟。
默认代码页由Windows将使用的语言决定。不同的语言需要不同的字符,单个代码页不足以容纳欧洲语言使用的所有字符。例如,您会发现某些中欧和东欧地区使用code page 1250

bq8i3lrv

bq8i3lrv3#

为什么Windows为控制台和非控制台提供不同的代码页?
由于向后兼容MS-DOS应用程序,这些应用程序仍然可以在16位和32位Windows上运行,而且许多应用程序还可以移植到Windows控制台。此外,从DOS使用Alt code的能力已经在用户中根深蒂固,如果他们不能再输入自己喜欢的特殊字符,他们会抱怨,所以DOS代码页是必须的
DOS最初使用内置于EGA和VGA ROM中的code page 437。但后来ISO和IEC共同制定了新的标准代码页,因此Microsoft很快加入进来,并在Windows中使用code page 1252,该代码页基于早期草案,后来成为ISO 8859-1
其原因在于Windows代码页1252最初基于ANSI草案,该草案后来成为ISO标准8859 - 1
Why is the default 8-bit codepage called "ANSI"?
事实上,微软一直是早期采用者。例如,它是第一个采用Korean standard的,并且是the first to use Unicode,这两个都是后来的遗憾。前者从未被其他人使用,而后者使得编写可移植代码变得困难,因为其他人都是后来的,使用更新更好的UTF-8代替
微软非常重视向后兼容性,所以在引入新的Windows代码页时,他们不能改变控制台应用程序的行为。因此,他们只能对GUI应用程序进行更改。因此,传统的Windows GUI应用程序(在Unicode出现之前)将使用ANSI代码页,而控制台应用程序仍将保留一个单独的代码页。还需要引入一种不同的输入特殊字符的方法:由Alt后的第一个数字小键盘键区分

  • 如果是数字小键盘1 - 9,则使用DOS代码页(A.K.AOEM代码页)。Alt +7将生成代码点7(CP437中的U +2022 "·")
  • 如果是numpad 0,则使用Windows代码页(A.K. A ANSI代码页)。Alt +0149将生成代码点149,与CP1252中的U +2022 "·"相同
  • 如果是numpad+,则输入十六进制UCS2/UTF-16。这是使用Unicode的新Windows GUI应用程序的新行为。键入Alt ++2022会得到相同的U +2022 "·"字符

请注意,这需要通过在HKCU\Control Panel\Input Method注册表项中设置名为EnableHexNumpadREG_SZ值来启用十六进制数字键盘,然后重新引导
另请参见Which character encoding is used for ALT-codes?
如何确定每台计算机的这些代码页?
每个语言环境都有4 different default associated code pages:OEM(DOS),ANSI(Windows),EBCDIC和Mac(经典)代码页,现在只有前两个是真正重要的。所以在安装Windows后,在默认的US语言环境下,你将分别拥有用于DOS和Windows的CP437和CP1252代码页。但是这些代码页可以很容易地更改,例如通过chcp,通过API调用或通过编辑注册表
同一台机器上的代码页之间有什么关系?控制台代码页和非控制台代码页之间有关联吗?
它们之间的唯一联系是与语言环境的联系
代码页为1252的计算机是否始终具有控制台代码页437?
不,因为代码页可以由用户更改,正如我所说的。此外,可能有非美国地区也使用CP1252,但默认使用另一个DOS代码页

sr4lhrrt

sr4lhrrt4#

如何确定每台计算机的这些代码页?
请查看此表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

相关问题