c++ - 在 C++ 源代码中使用重音字符是不是很糟糕?

标签 c++ unicode portability

我希望我的程序尽可能便携。我在字符串中搜索重音字符,例如è.这可能是个问题吗?是否有等效于 HTML 实体的 C++?

它将在 switch 语句中使用,例如:

switch(someChar) //someChar is of type char
{
   case 'é' :
        x = 1;
        break;
   case 'è' :
   ...
}

最佳答案

在 C++ 源代码中使用非 ASCII 字符的主要问题是编译器必须知道用于源代码的编码。如果源是 7 位 ASCII,那么它通常无关紧要,因为大多数编译器默认情况下都假定 ASCII 兼容编码。

此外,并非所有编译器都可以在编码方面进行配置,因此两个编译器可能会无条件地使用不兼容的编码,这意味着使用非 ASCII 字符可能会导致源代码无法与两者一起使用。

  • GCC:具有用于设置源、执行和广泛执行编码的命令行选项。默认值由区域设置设置,这些天通常使用 UTF-8。
  • MSVC:使用所谓的“BOM”来确定源编码(介于 UTF-16BE/LE、UTF-8 和系统区域设置编码之间),并且始终使用系统区域设置作为执行编码。 编辑:从 VS 2015 Update 2 开始,MSVC 支持编译器切换来控制源和执行字符集,包括对 UTF-8 的支持。 see here
  • Clang:始终使用 UTF-8 作为源和执行编码

  • 因此,请考虑如果要搜索的字符串是 UTF-8(可能是因为执行字符集是 UTF-8),那么您的代码在搜索重音字符时会发生什么情况。无论字 rune 字 'é' 是否按您的预期工作,您都不会找到重音字符,因为重音字符不会由任何单个字节表示。相反,您必须搜索各种字节序列。

    C++ 允许在字符和字符串文字中使用不同类型的转义。通用字符名称允许您指定一个 Unicode 代码点,并且将完全按照该字符出现在源代码中的方式进行处理。例如 \u00E9\U000000E9 .

    (其他一些语言有 \u 来支持高达 U+FFFF 的代码点,但缺乏 C++ 对超出此范围的代码点的支持,或者让您使用代理代码点。您不能在 C++ 中使用代理代码点,而 C++ 有\U 变体来支持直接所有代码点。)

    UCN 也应该在字符和字符串文字之外工作。在此类文字之外,UCN 仅限于不在基本源字符集中的字符。然而,直到最近,编译器还没有实现这个 (C++98) 特性。现在 Clang 似乎有相当完整的支持,MSVC 似乎至少有部分支持,GCC 声称通过选项 -fextended-identifiers 提供实验性支持。 .

    回想一下,UCN 应该与源中出现的实际字符一视同仁;因此,具有良好 UCN 标识符支持的编译器还允许您使用实际字符简单地编写标识符,只要编译器的源编码首先支持该字符。

    C++ 还支持十六进制转义。这些是\x 后跟任意数量的十六进制数字。十六进制转义将表示单个整数值,就好像它是具有该值的单个代码点,并且不会对该值进行到执行字符集的转换。如果您需要表示独立于编码的特定字节(或 char16_t、或 char32_t、或 wchar_t)值,那么这就是您想要的。

    还有八进制转义,但它们不如 UCN 或十六进制转义那么有用。

    以下是在使用 ISO-8859-1 或 cp1252 编码的源文件中使用“é”时 Clang 显示的诊断信息:
    warning: illegal character encoding in character literal [-Winvalid-source-encoding]
        std::printf("%c\n",'<E9>');
                           ^
    

    Clang 仅将此作为警告发出,并且将直接输出带有源字节值的 char 对象。这样做是为了与非 UTF-8 源代码向后兼容。

    如果您使用 UTF-8 编码的源代码,那么您会得到:
    error: character too large for enclosing character literal type
        std::printf("%c\n",'<U+00E9>');
                           ^
    

    Clang 检测到 UTF-8 编码对应于 Unicode 代码点 U+00E9,并且该代码点超出了单个字符可以容纳的范围,因此报告错误。 (Clang 也会对非 ASCII 字符进行转义,因为它确定运行它的控制台无法处理打印非 ASCII 字符)。

    关于c++ - 在 C++ 源代码中使用重音字符是不是很糟糕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11996127/

    相关文章:

    python - 如何将 Python 中的双 UTF-8 解码器代码转换为 Lua

    c - libunistring u8_strlen() 等于 strlen()?

    migration - MediaWiki 到 Confluence 迁移

    c++ - boost asio deadline_timer

    c++ - 没有调试器的版本中的访问冲突

    swift - 使用 Swift 语言从字节数组创建 NSString 会生成错误的字符

    c# - UWP - 使用 sqlite 的可移植类库。我是否误解了诱饵+开关组件?

    c++ - 在 Xcode 中使用带有相对路径的 SDL_LoadBMP 有困难

    c++ - 有NPM之类的C++项目管理器吗?

    c++ - 调用函数后程序忽略所有内容