[英]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";
字符串文字( L
, u
, U
)的大小修饰符仅确定文字的类型 。
编译器如何解释这些新类型的字符串文字中包含非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.