编译/运行时字符串文字的原始字节流入/流出 Windows(非宽)执行字符集,以及 ANSI 代码页与 UTF-8

2024-03-22

我想确认我对原始字符串文字和(非宽)的理解execution character set在 Windows 上。

我希望具体确认的相关段落以粗体显示。但首先,有一些背景知识。


背景

(相关问题见下文bold)

由于下面的有益讨论@TheUndeadFish 的回答 https://stackoverflow.com/a/27871269/368896 to 我昨天发布的这个问题 https://stackoverflow.com/questions/27871124/does-the-multibyte-to-wide-string-conversion-function-mbstowcs-when-passed-a,我试图理解决定的规则字符集 and encoding用作execution character set在 Windows 上的 MSVC 中(在 C++ 规范意义上execution character set; see @DietmarKühl 的帖子 https://stackoverflow.com/questions/27872517/what-are-the-different-character-sets-used-for).

我怀疑有些人可能会认为尝试理解 ANSI 相关行为是浪费时间。char *MSVC 中非 ASCII 字符的(即非宽)字符串。

例如,考虑@IInspectable 的评论在这里 https://stackoverflow.com/q/27871124/368896:

您不能将 UTF-8 编码的字符串扔到 ANSI 版本的 Windows API 并希望一切正常。

请注意,在我当前基于 Windows MFC 应用程序的 i18n 项目中,我将removing对 API 调用的非宽(即 ANSI)版本的所有调用,我希望编译器生成execution wide-character set字符串,NOT execution character set(非宽)内部字符串。

然而,我想理解现有代码已经具有一些使用 ANSI API 函数的国际化。即使有些人认为 ANSI API 对非 ASCII 字符串的行为很疯狂,我也想理解它。

我认为像其他人一样,我发现很难找到有关非广泛的澄清文档execution character set在 Windows 上。

特别是,因为(非宽)execution character set由 C++ 标准定义为一个序列char(相对于wchar_t),UTF-16不能在内部使用来存储非宽字符execution character set。在当今时代,通过 UTF-8(achar基于编码),因此将用作字符集和编码execution character set。据我了解,Linux 上就是这样。然而,可悲的是,这是notWindows 上的情况 - 甚至是 MSVC 2013。

这引出了我的两个问题中的第一个问题。


问题#1: 请确认我在以下段落中的正确性。

有了这个背景,我的问题就来了。在MSVC中,包括VS 2013,似乎execution character set是(许多可能的)ANSI 字符集之一,使用(许多可能的)字符集之一代码页对应于特定给定的 ANSI 字符集来定义编码——而不是用 UTF-8 编码的 Unicode 字符集。(请注意,我问的是非宽execution character set。) 它是否正确?


背景(续)(假设我在问题#1中是正确的)

如果我理解正确的话,上面的粗体段落可以说是在 Windows 上使用 ANSI API 的“疯狂”原因的很大一部分。

具体来说,考虑“正常”情况 - 其中 Unicode 和 UTF-8 用作execution character set.

在这种情况下,代码在什么机器上或何时编译并不重要,并且代码在什么机器上或何时运行也无关紧要。字符串文字的实际原始字节始终在内部以 UTF-8 编码的 Unicode 字符集表示,并且运行时系统在语义上始终将此类字符串视为 UTF-8。

在“疯狂”的情况下就没有这样的运气了(如果我理解正确的话),其中 ANSI 字符集和代码页编码被用作execution character set。在这种情况下(Windows 世界),运行时行为可能是affected与代码运行的机器相比,编译代码的机器。


那么,这是问题#2:再次请确认我在以下段落中的正确性。

考虑到这一背景,我怀疑:具体来说,对于 MSVC,execution character set它的编码以某种不太容易理解的方式取决于由compiler在编译时,在运行编译器的机器上。这将确定“烧录”到可执行文件中的字符文字的原始字节。并且,在运行时,MSVC C 运行时库可能正在使用不同的 execution character set并编码为解释烧录到可执行文件中的字符文字的原始字节。我对么?

(我可能会在某个时候在这个问题中添加例子。)


最终评论

从根本上来说,如果我理解正确的话,上面的粗体段落解释了在 Windows 上使用 ANSI API 的“疯狂”。由于 ANSI 字符集和所选择的编码之间可能存在差异compiler由于 C 运行时选择的 ANSI 字符集和编码,当程序中使用 ANSI API 时,字符串文字中的非 ASCII 字符可能不会按预期出现在正在运行的 MSVC 程序中。

(请注意,ANSI“疯狂”实际上仅适用于字符串文字,因为根据 C++ 标准,实际的源代码必须以 ASCII 的子集编写(并且源代码注释将被编译器丢弃)。)

上面的描述是我目前对 Windows 上的 ANSI API 字符串文字的最好理解。我想确认我的解释是正确的并且我的理解是正确的。


这是一个很长的故事,我很难找到一个明确的问题。不过,我认为我可以解决导致这一情况的一些误解。

首先,“ANSI”是(窄)执行字符集的同义词。 UTF-16 是执行宽字符集。

编译器不会为你选择。如果您使用窄char字符串,就编译器(运行时)所知,它们是 ANSI 的。

是的,特定的“ANSI”字符编码可能很重要。如果你编译一个L"ä"字面量在你的PC上,并且你的源代码在CP1252中,那么ä字符被编译为 UTF-16ä。但是,同一字节可能是其他编码中的另一个非 ASCII 字符,这将导致不同的 UTF-16 字符。

但请注意,MSVCis完全能够编译 UTF-8 和 UTF-16 源代码,只要它以U+FEFF“物料清单”。这使得整个理论问题几乎不再是问题。

[编辑] “具体来说,与MSVC,执行字符集及其编码取决于...”

不,MSVC 与执行字符集无关,真的。的含义char(0xE4)由操作系统决定。要查看这一点,请检查 MinGW 编译器。 MinGW 生成的可执行文件的行为与 MSVC 的相同,因为两者都针对相同的操作系统。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编译/运行时字符串文字的原始字节流入/流出 Windows(非宽)执行字符集,以及 ANSI 代码页与 UTF-8 的相关文章

随机推荐