gpt4 book ai didi

c++ - u8-literals 应该如何工作?

转载 作者:IT老高 更新时间:2023-10-28 23:15:09 40 4
gpt4 key购买 nike

无法理解 u8-literals 的语义,或者更确切地说,无法理解 g++ 4.8.1 的结果

这是我的期望:

const std::string utf8 = u8"åäö"; // or some other extended ASCII characters
assert( utf8.size() > 3);

这是 g++ 4.8.1 的结果
const std::string utf8 = u8"åäö"; // or some other extended ASCII characters
assert( utf8.size() == 3);
  • 源文件是 ISO-8859(-1)
  • 我们使用这些编译器指令:-m64 -std=c++11 -pthread -O3 -fpic

  • 在我的世界中,无论源文件的编码如何,生成的 utf8 字符串都应该长于 3。

    或者,我是否完全误解了 u8 的语义以及它所针对的用例?请赐教。

    更新

    如果我像许多人建议的那样明确告诉编译器源文件的编码是什么,我就会得到 u8 文字的预期行为。 但是 , 常规文字也被编码为 utf8

    那是:
    const std::string utf8 = u8"åäö"; // or some other extended ASCII characters
    assert( utf8.size() > 3);
    assert( utf8 == "åäö");
  • 编译器指令: g++ -m64 -std=c++11 -pthread -O3 -finput-charset=ISO8859-1
  • 尝试了一些从 iconv 定义的其他字符集,例如:ISO_8859-1 等等...

  • 我现在比以前更糊涂了……

    最佳答案

    u8前缀实际上只是意味着“在编译此代码时,从该文字生成一个 UTF-8 字符串”。它没有说明编译器应该如何解释源文件中的文字。

    所以你有几个因素在起作用:

  • 哪种编码是写入的源文件(在您的情况下,显然是 ISO-8859)。根据这种编码,字符串文字是“åäö”(3 个字节,包含值 0xc5、0xe4、0xf6)
  • 编译器在读取源文件时采用哪种编码? (我怀疑 GCC 默认为 UTF-8,但我可能错了。
  • 编译器用于目标文件中生成的字符串的编码。您可以通过 u8 将其指定为 UTF-8字首。

  • 最有可能的是,#2 是出现问题的地方。如果编译器将源文件解释为 ISO-8859,那么它将读取这三个字符,将它们转换为 UTF-8,然后写入这些字符,为您提供一个 6 字节(我认为这些字符中的每一个都在 UTF 中编码为 2 个字节) -8) 作为结果的字符串。

    但是,如果它假定源文件是 UTF-8,那么它根本不需要进行转换:它读取 3 个字节,它假定是 UTF-8(即使它们是 UTF-8 的无效垃圾值) -8),并且由于您要求输出字符串也为 UTF-8,因此它只输出相同的 3 个字节。

    您可以使用 -finput-charset 告诉 GCC 假定采用哪种源编码。 ,或者您可以将源编码为 UTF-8,或者您可以使用 \uXXXX字符串文字中的转义序列(例如 \u00E5 而不是 å )

    编辑:

    澄清一下,当您使用 u8 指定字符串文字时源代码中的前缀,然后您告诉编译器“无论您在读取源文本时使用哪种编码,请在将其写入目标文件时将其转换为 UTF-8”。你没有说应该如何解释源文本。这由编译器决定(可能基于您传递给它的标志,可能基于进程的环境,或者可能只是使用硬编码的默认值)

    如果源文本中的字符串包含字节 0xc5、0xe4、0xf6,并且您告诉它“源文本编码为 ISO-8859”,那么编译器将识别“该​​字符串由字符“åäö”组成。它将看到 u8 前缀,并将这些字符转换为 UTF-8,将字节序列 0xc3, 0xa5, 0xc3, 0xa4, 0xc3, 0xb6 写入目标文件。在这种情况下,您最终会得到一个有效的 UTF- 8 个编码的文本字符串,包含字符“åäö”的 UTF-8 表示。

    但是,如果源文本中的字符串包含相同的字节,并且您让编译器相信源文本被编码为 UTF-8,那么编译器可能会做两件事(取决于实现:
  • 它可能会尝试将字节解析为 UTF-8,在这种情况下,它会识别出“这不是有效的 UTF-8 序列”,并发出错误消息。这就是 Clang 所做的。
  • 或者,它可能会说“好吧,我这里有 3 个字节,我被告知假设它们形成了一个有效的 UTF-8 字符串。我会捕获它们,看看会发生什么”。然后,当它应该将字符串写入目标文件时,它会“好吧,我有这 3 个之前的字节,它们被标记为 UTF-8。这里的 u8 前缀意味着我应该写此字符串为 UTF-8。很酷,然后不需要进行转换。我将只写这 3 个字节,我就完成了”。这就是 GCC 所做的。

  • 两者都有效。 C++ 语言没有声明编译器需要检查传递给它的字符串文字的有效性。

    但在这两种情况下,请注意 u8前缀与您的问题无关。这只是告诉编译器从“读取字符串时使用的任何编码转换为 UTF-8”。但即使在这种转换之前,字符串就已经是乱码了,因为字节对应于 ISO-8859 字符数据,但编译器认为它们是 UTF-8(因为你没有告诉它其他)。

    您看到的问题只是编译器在从源文件中读取字符串文字时不知道要使用哪种编码。

    您注意到的另一件事是,没有前缀的“传统”字符串文字将使用编译器喜欢的任何编码进行编码。 u8前缀(以及相应的 UTF-16 和 UTF-32 前缀)被精确地引入,以允许您指定希望编译器将输出写入的编码。普通的无前缀文字根本不指定编码,而是保留它由编译器决定。

    关于c++ - u8-literals 应该如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23471935/

    40 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com