【问题标题】:Are there any unicode/wide chars that encode to multiple encoded characters是否有任何 unicode/wide 字符编码为多个编码字符
【发布时间】:2015-07-25 04:05:54
【问题描述】:

考虑 wctomb(),它采用宽字符并编码为当前选定的字符集。 glibc 手册页声明输出缓冲区应该是 MB_CUR_MAX,而 FreeBSD 手册页声明输出缓冲区大小应该是 MB_LEN_MAX。这里哪个是正确的?

是否有任何示例宽字符/编码组合需要多个编码字符来表示宽字符?

更一般地说,MB_CUR_MAX 是指最大组合编码字符字节数以表示宽字符,还是仅表示任何特定编码字符的最大字节数?

【问题讨论】:

    标签: c character-encoding internationalization


    【解决方案1】:

    MB_CUR_MAX 是正确的,但两者都足够大。如果你想避免可变长度数组声明,你可能想使用MB_LEN_MAX。

    MB_CUR_MAX 是当前语言环境 中多字节字符的最大字节数。 MB_LEN_MAX 是任何支持的语言环境的字符中的最大字节数。与MB_CUR_MAX 不同,MB_LEN_MAX 是一个宏,因此可以在数组声明中使用它而无需创建 VLA。

    这两个常量都指向一个宽字符。多字节字符到底是什么并没有简单的定义,因为多字节编码可以包括移位序列;如果多字节语言环境包含移位序列,则对具有特定宽字符的wctomb 的特定调用所需的字节数可能因调用而异,具体取决于移位状态。 (另外,实际代码在不同的移位状态下可能会有所不同。)

    据我所知,没有什么可以阻止宽字符被转换为多字节序列,而多字节序列可以分解为其他多字节序列(如 Unicode 组合); wctomb 的定义仅涉及“表示”。但我也不知道有什么实现可以做到这一点; Unicode 规范分解必须使用单独的 API 来完成。

    因此,可能没有安装的语言环境需要像 MB_LEN_MAX 这样大的值。但是,只要不超过编码限制(Linux 上为 16 字节),您就可以添加语言环境(甚至创建自己的语言环境)。

    【讨论】:

    • 是的,我看到了运行时常量和编译时常量之间的区别,但我不相信这些常量是否指的是单个编码字符。让我换个方式问。如果 MB_LEN_MAX 只表示单个编码字符,那么什么编码的字符需要 16 个字节(这是 GNU/Linux 上的值)
    • @pixelbeat: 没有(据我所知),但您可以创建自己的多字节语言环境,前提是您没有定义编码需要超过 16 个字符的字符字节。常量指的是单个字符。我会编辑答案。
    • 感谢您的详细回答。我看到 iso-2022-kr 每个字符最多占用 7 个字节,这就是让我怀疑 MB_LEN_MAX 可能太大而无法容纳多个字符(2 + 对齐)的原因。默认情况下,在我的 Fedora 22 系统上,UTF8 的最大 MB_CUR_MAX 为 6,其他各种编码占用 2,3 或 4 个字节。我仍然不确定为什么 MB_LEN_MAX 这么大。
    • 我询问了 Bruno Haible,他在lists.gnu.org/archive/html/bug-gnulib/2015-05/msg00001.html 上回答并基本上同意这个答案。 IE。在 POSIX 和 glibc 中,宽字符和编码字符之间存在 1:1 映射,MB_LEN_MAX=16 仅用于未来验证
    • 如果某个库认为“UTF8 在 6 处具有最大的 MB_CUR_MAX”,那么这是一个错误。有效的 UTF-8 最多可以有 4 个字节。最多 6 个字节的变体称为“CESU”,“这样的编码不符合定义的 UTF-8”。 (见unicode.org/faq/utf_bom.html#utf8-4)。最多 6 个字节的另一种方法是,如果您表示超出 U+10FFFF 的字符,这(再次)是无效的 Unicode (unicode.org/faq/utf_bom.html#gen6)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-17
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多