3

在 C11 中,支持可移植的宽字符类型char16_t,并char32_t分别添加了 UTF-16 和 UTF-32。

然而,在技术报告中,并没有提到这两种类型的字节序。

例如,以下代码片段在gcc-4.8.4我的 x86_64 计算机上编译时使用-std=c11

#include <stdio.h>
#include <uchar.h>

char16_t utf16_str[] = u"十六";  // U+5341 U+516D
unsigned char *chars = (unsigned char *) utf16_str;
printf("Bytes: %X %X %X %X\n", chars[0], chars[1], chars[2], chars[3]);

会产生

Bytes: 41 53 6D 51

这意味着它是小端的。

char16_t但是这种行为是否依赖于平台/实现:它是否始终遵守平台的字节序,或者某些实现可能选择始终char32_t大字节序实现?

4

3 回答 3

6

char16_t并且char32_t不保证 Unicode 编码。(这是一个 C++ 特性。)宏__STDC_UTF_16____STDC_UTF_32__分别表示 Unicode 代码点实际上决定了固定大小的字符值。有关这些宏,请参见 C11 §6.10.8.2。

(顺便说一下,__STDC_ISO_10646__表示相同的东西wchar_t,它还揭示了哪个Unicode版本是通过 实现wchar_t的。当然,在实践中,编译器只是将代码点从源文件复制到目标文件中的字符串,所以它不会需要对特定字符有很多了解。)

鉴于 Unicode 编码有效,存储在char16_tor中的代码点值必须具有与和char32_t相同的对象表示,因为它们分别被定义为这些类型的别名(C11 §7.28)。这再次与 C++ 形成对比,C++ 使这些类型不同,但明确要求兼容的对象表示。uint_least16_tuint_least32_ttypedef

char16_t结果是,是的,和没有什么特别之处char32_t。它们是平台字节序中的普通整数。

但是,您的测试程序与字节序无关。它只是使用宽字符的值,而不检查它们如何映射到内存中的字节。

于 2015-07-15T14:57:36.797 回答
3

然而,在技术报告中,并没有提到这两种类型的字节序。

确实。C 标准没有详细说明源文件中多字节字符的表示。

char16_t utf16_str[] = u"十六"; // U+5341 U+516D
printf("U+%X U+%X\n", utf_16_str[0], utf_16_str[1]);

将产生 U+5341 U+516D 这意味着它是小端的。

char16_t但是这种行为是否依赖于平台/实现:它是否始终遵循平台的字节序,或者某些实现可能选择始终char32_t以大字节序实现?

的,正如你所说的,行为是依赖于实现的。见 C11§5.1.1.2:

如有必要,物理源文件多字节字符以实​​现定义的方式映射到源字符集(为行尾指示符引入换行符)。

也就是说,源代码中的多字节字符被认为是大端还是小端是实现定义的。u"\u5341\u516d"如果可移植性是一个问题,我会建议使用类似的东西。

于 2015-07-15T14:53:49.360 回答
0

UTF-16 和 UTF-32 没有定义字节顺序。它们通常以主机本机字节顺序编码。这就是为什么可以在字符串开头插入字节顺序标记 (BOM) 以指示 UTF-16 或 UTF-32 字符串的字节顺序。

于 2019-05-23T12:00:37.303 回答