首页 文章

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

提问于
浏览
10

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

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

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

对于代码示例猴子:

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的经验告诉我,这绝对是实现定义的,可能只有第一个才能做我想要的 .

3 回答

  • 0

    在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 )仅确定文字的 type .

  • 8

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

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

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

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

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

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

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

    基本源集是允许字符的简单列表 . 它不是ASCII(进一步参见) . 不在此列表中的任何内容都是'transformed'(至少在概念上)是 \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!";
    
  • 5

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

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

相关问题