【问题标题】:gcc, UTF-8 and limits.hgcc、UTF-8 和 limits.h
【发布时间】:2011-02-09 10:29:41
【问题描述】:

我的操作系统是 Debian,我的默认语言环境是 UTF-8,我的编译器是 gcc。默认情况下,limits.h 中的 CHAR_BIT 为 8,这对于 ASCII 来说是可以的,因为在 ASCII 中 1 char = 8 位。但由于我使用的是 UTF-8,字符最多可以为 32 位,这与 CHAR_BIT 默认值 8 相矛盾。

如果我在limits.h 中将CHAR_BIT 修改为32 以更好地适应UTF-8,我需要做什么才能使这个新值生效?我想我必须重新编译 gcc ?我必须重新编译linux内核吗?那么默认安装的 Debian 软件包呢,它们会起作用吗?

【问题讨论】:

    标签: c linux gcc utf-8 locale


    【解决方案1】:

    CHAR_BITchar 中的位数;永远,永远改变这一点。它不会有你想要的效果。

    如果您想直接存储 Unicode 字符,请使用 UTF-8 编码的 chars 字符串,或者使用 wchar_t 字符串。*

    * 小字体:wchar_t 的大小也取决于系统。在带有 MSVC 的 Windows 上,它只有 16 位,仅对基本多语言平面足够。不过,您可以将它与 UTF-16 一起使用,它与 Windows API 配合得很好。在大多数其他系统上,wchar_t 为您提供完整的 32 位。

    【讨论】:

    • 不是我想要的效果?会有什么效果?
    • @bobby:char 的大小不会改变。它仍然是 8 位。效果将是使用CHAR_BIT 作为char 中位数的代码将中断,正如dan04 所说。
    【解决方案2】:

    您不需要 char 为 32 位即可进行 UTF-8 编码。 UTF-8 是变长编码,专为 8 位字符设计,向后兼容 ascii。

    您也可以使用 32 位的wchar_t(在 Linux 上),但通常您不会使用它 更多的附加值,因为 Unicode 处理比代码点管理复杂得多。

    【讨论】:

    • 我真的很想继续使用 char 而不是使用 wchar_t。
    【解决方案3】:

    C 和 C++ 将char 定义为一个字节,即sizeof 返回 1 的整数类型。它不一定是 8 位,但绝大多数时候是。恕我直言,它应该被命名 byte。但早在 1972 年创建 C 时,西方人不必处理多字节字符编码,因此您可以将“字符”和“字节”类型混为一谈。

    您只需要忍受令人困惑的术语即可。或typedef 离开。但不要编辑您的系统头文件。如果您想要字符类型而不是字节类型,请使用wchar_t

    但 UTF-8 字符串由 8 位代码单元组成,因此 char 可以正常工作。您只需要记住char 和字符之间的区别。例如,不要这样做:

    void make_upper_case(char* pstr)
    {
       while (*pstr != '\0')
       {
          *pstr = toupper(*pstr);
          pstr++;
       }
    }
    

    toupper('a') 按预期工作,但 toupper('\xC3') 是对字符的大写一半的荒谬尝试。

    【讨论】:

      【解决方案4】:

      UTF-8 将 1 个字符编码为几个字节。

      另外,不要编辑您的系统头文件。 (不,修改 CHAR_BITS 将不起作用,重新编译内核/gcc 或其他)。

      【讨论】:

      • 是的,所以 strlen() 会说欧元符号(3 个字节)的长度为 3 个字符,这是不正确的;它有 1 个字符长。如果我将 CHAR_BIT 修改为 32,这种行为会得到纠正吗?
      • 不,@bobby。您需要使用 Unicode 感知库,例如 ICU。
      • strlen 正确地说你的 3 字节欧元符号是 3 字节。 strlen 不计算字符,它计算字节(尽管它们对于 ascii 来说是相同的)。您很少需要知道否。字符,除非您正在编写屏幕显示或布局内容。如果您愿意,请使用 wchar_t,或者使用方便的 UTF-8 库,正如其他人所建议的那样。永远不要修改 CHAR_BITS。不要考虑修改系统头文件。
      • Bobby,计算字符绝非易事,而且 strlen 不像您遇到的几乎任何其他 API 那样做到这一点。举个例子:单词“שָלוֹם”由 4 个字符组成,但有 6 个 Unicode 代码点。
      • 虽然 wcslen 确实可能不会计算 UTF-16 的字符数,但它会在 linux 上用于所有实际目的(直到 unicode 超过 32 位......) - 因为 wchar_ts 在那里是 utf-32 .
      【解决方案5】:

      我很确定 CHAR_BIT 是 'char' 变量类型中的位数,不是任何字符的最大位数。正如您所注意到的,它在limits.h 中是一个常数,不会根据区域设置而改变。

      CHAR_BIT 在任何相当新/健全的系统上都将等于 8...非 8 位字现在很少见 :)

      【讨论】:

      • CHAR_BIT 保证永远不会小于 8,因此对于 UTF-8 数据是安全的。
      猜你喜欢
      • 2020-08-13
      • 1970-01-01
      • 2010-10-26
      • 2020-12-09
      • 2017-05-07
      • 1970-01-01
      • 2022-07-30
      • 2011-10-11
      • 2017-05-19
      相关资源
      最近更新 更多