繁体   English   中英

文件编码如何影响C ++ 11字符串文字?

[英]How does file encoding affect C++11 string literals?

您可以在C ++ 11中编写UTF-8/16/32字符串文字,方法是将字符串文字分别加上u8 / u / U 编译器如何解释这些新类型的字符串文字中包含非ASCII字符的UTF-8文件? 我理解标准没有指定文件编码,而这个事实本身就会使源代码中非ASCII字符的解释完全未定义的行为,使得这个特性有点不太有用。

我知道你仍然可以使用\\uNNNN来逃避单个unicode字符,但这对于完整的俄语或法语句子来说并不是很易读,因为它通常包含多个unicode字符。

我从各种来源得到的理解是,在当前的Windows实现中, u应该等同于L ,在Linux实现上, u应该等同于U 因此,考虑到这一点,我也想知道旧字符串文字修饰符所需的行为是什么......

对于代码示例猴子:

string utf8string a = u8"L'hôtel de ville doit être là-bas. Ça c'est un fait!";
string utf16string b = u"L'hôtel de ville doit être là-bas. Ça c'est un fait!";
string utf32string c = U"L'hôtel de ville doit être là-bas. Ça c'est un fait!";

在理想的世界中,所有这些字符串都产生相同的内容(如:转换后的字符),但我使用C ++的经验告诉我,这绝对是实现定义的,可能只有第一个才能做我想要的。

在GCC中,使用-finput-charset=charset

设置输入字符集,用于从输入文件的字符集转换为GCC使用的源字符集。 如果区域设置未指定,或GCC无法从区域设置获取此信息,则默认值为UTF-8。 这可以通过语言环境或此命令行选项覆盖。 目前,如果存在冲突,命令行选项优先。 charset可以是系统的“iconv”库例程支持的任何编码。

另请查看选项-fexec-charset-fwide-exec-charset

最后,关于字符串文字:

char     a[] = "Hello";
wchar_t  b[] = L"Hello";
char16_t c[] = u"Hello";
char32_t d[] = U"Hello";

字符串文字( LuU )的大小修饰符仅确定文字的类型

编译器如何解释这些新类型的字符串文字中包含非ASCII字符的UTF-8文件。 我理解标准没有指定文件编码,而这个事实本身就会使源代码中非ASCII字符的解释完全未定义的行为,使得这个特性有点不太有用。

来自n3290,2.2阶段的翻译[lex.phases]

如果需要,物理源文件字符以实现定义的方式映射到基本源字符集(引入行尾指示符的换行符)。 接受的物理源文件字符集是实现定义的。 [ 这里有一些关于三元组的内容。 不在基本源字符集(2.3)中的任何源文件字符将替换为指定该字符的通用字符名称。 (实现可以使用任何内部编码,只要在源文件中遇到实际扩展字符,并且在源文件中表示为与通用字符名称相同的扩展字符(即,使用\\ uXXXX表示法),处理等效,除非在原始字符串文字中还原此替换。)

有很多标准术语用于描述实现如何处理编码。 这是我尝试对所发生的事情进行更为简单,逐步的描述:

物理源文件字符以实现定义的方式映射到基本源字符集[...]

文件编码的问题是handwaved; 标准只关心基本的源字符集,并为实现提供了空间。

不在基本源字符集(2.3)中的任何源文件字符将替换为指定该字符的通用字符名称。

基本源集是允许字符的简单列表。 它不是ASCII (进一步参见)。 不在此列表中的任何内容都“转换”(至少在概念上)为\\uXXXX表单。

因此,无论使用何种文字或文件编码,源代码都在概念上转换为基本字符集+一堆\\uXXXX 我在概念上说,因为实现的实际操作通常更简单,例如因为它们可以直接处理Unicode。 重要的是,标准调用扩展字符(即不是来自基本源集)的内容应该与其等效的\\uXXXX形式无法区分。 请注意,C ++ 03可用于例如EBCDIC平台,因此您在ASCII方面的推理存在缺陷。

最后,我描述的过程也发生在(非原始的)字符串文字上。 这意味着您的代码与您编写的代码相同:

string utf8string a = u8"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!";
string utf16string b = u"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!";
string utf32string c = U"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!";

原则上,编码问题只有在输出字符串时才会对人类可见,这不是编程语言如何定义的问题,因为它的定义只涉及编码计算。 所以,当你决定,你在编辑器中看到的内容是否与你在输出中看到的相同(任何类型的图像,无论是在屏幕上还是在pdf中),你应该问自己哪个约定用户交互库和操作系统编码的方式假设。 (例如,这是Qt5的这种信息:使用Qt5,你看到的应用程序的用户和你看到的程序员一致,如果你的QStrings的老式字符串文字的内容被编码作为源文件中的utf8,除非您在应用程序执行过程中打开另一个设置)。

总之,我认为Kerrek SB是正确的,Damon是错误的:实际上,在代码中指定文字的方法应该指定其类型,而不是源文件中用于填充其内容的编码,如文字的类型是计算所做的事情。 类似于u"string"东西只是一个“unicode codeunits”(即char16_t类型的值)的char16_t ,无论操作系统或任何其他服务软件以后对它们做什么,然而它们的工作为您或其他用户寻找。 你只是遇到了为自己添加另一个约定的问题,它使计算中数字的“含义”(即,它们呈现Unicode的代码)之间的对应关系,以及当你在文本编辑器中工作时它们在屏幕上的表示。 如何以及作为程序员使用“意义”是另一个问题,如何强制执行其他对应关系自然会被实现定义,因为它与编码计算无关,只是工具使用的舒适性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM