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



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

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


背景

(相关问题见bold中的以下段落)

由于@TheUndeadFish对我昨天发布的这个问题的回答下面进行了有益的讨论,我试图理解确定Windows上MSVC中用作execution character set字符集编码的规则(在execution character set的C++规范意义上;请参阅@DietmarKühl的帖子)。

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

例如,考虑@IInspectable在此处的评论:

您不能在ANSI版本的Windows API,希望任何正常的事情都能发生。

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

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

我想和其他人一样,我发现很难在Windows上找到关于非宽execution character set的澄清文档。

特别地,因为(非宽)execution character set由C++标准定义为char的序列(与wchar_t相反),所以UTF-16不能在内部用于在非宽execution character set中存储字符。在这个时代,通过UTF-8(一种基于char的编码)编码的Unicode字符集将被用作execution character set的字符集和编码,这是有道理的。据我所知,Linux就是这样。然而,遗憾的是,这不是在Windows上的情况,甚至是MSVC 2013。

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


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

在这种背景下,这是我的问题在MSVC(包括VS 2013)中,execution character set似乎是(许多可能的)ANSI字符集之一,使用与特定给定ANSI字符集相对应的(许多可能)代码页之一来定义编码,而不是使用UTF-8编码的Unicode字符集(请注意,我询问的是非广域execution character set。)这是正确的吗?


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

如果我理解正确的话,以上粗体段落可以说是在Windows上使用ANSI API"疯狂"的主要原因。

具体来说,考虑一下"sane"的情况,即使用Unicode和UTF-8作为execution character set

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

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


这里是问题2:再次确认我在下面的段落中是正确的。

考虑到这一持续的背景,我怀疑:特别是,对于MSVC,execution character set及其编码在某种程度上不太容易理解,取决于编译时编译器运行的机器上编译器选择的区域设置。这将确定"烧入"可执行文件的字符文字的原始字节。而且,在运行时,MSVC C运行库可能使用不同的execution character set并进行编码,以解释烧入可执行文件的字符文本的原始字节我说得对吗?

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


最终评论

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

(请注意,ANSI的"疯狂"实际上只适用于字符串文字,因为根据C++标准,实际的源代码必须写在ASCII的子集中(编译器会丢弃源代码注释)。)

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

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

首先,"ANSI"是(窄)执行字符集的同义词。UTF-16是执行范围内的字符集。

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

是的,特定的"ANSI"字符编码可能很重要。如果您在PC上编译L"ä"文字,并且源代码在CP1252中,则该ä字符将编译为UTF-16ä。然而,同一字节可能是其他编码中的另一个非ASCII字符,这将导致不同的UTF-16字符。

但是请注意,只要MSVC以U+FEFF"BOM"开头,它就完全能够编译UTF-8和UTF-16源代码。这使得整个理论问题几乎成为一个非问题。

[编辑]"特别是,对于MSVC,执行字符集及其编码取决于…">

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

最新更新