【发布时间】:2017-02-02 20:22:20
【问题描述】:
假设只有C99 Standard 纸和printf 库函数需要根据此标准实现以使用UTF-16 编码,您能否阐明s 指定精度转换的预期行为?
s 转换的 C99 标准 (7.19.6.1) 说:
如果不存在 l 长度修饰符,则参数应为指向字符类型数组的初始元素的指针。数组中的字符被写入(但不包括)终止空字符。如果指定了精度,则写入的字节数不会超过这个数。如果未指定精度或大于数组的大小,则数组应包含空字符。
如果存在 l 长度修饰符,则参数应为指向 wchar_t 类型数组的初始元素的指针。数组中的宽字符被转换为多字节字符(每个都好像通过调用 wcrtomb 函数,在转换第一个宽字符之前由 mbstate_t 对象描述的转换状态初始化为零)直到并包括终止的空宽特点。生成的多字节字符最多写入(但不包括)终止空字符(字节)。如果未指定精度,则数组应包含空宽字符。如果指定了精度,则写入的字节数不超过(包括移位序列,如果有的话),并且如果要等于由精度给出的多字节字符序列长度,则数组应包含一个空宽字符,该函数需要访问数组末尾的一个宽字符。在任何情况下都不会写入部分多字节字符。
总的来说,我不太理解这一段,特别是“如果指定了精度,则写入的字节数不超过”。
我们以 UTF-16 字符串“TEST”为例(字节序列:0x54、0x00、0x45、0x00、0x53、0x00、0x54、0x00)。
在以下情况下预计会写入输出缓冲区的内容:
- 如果 精度 为 3
- 如果 precision 为 9(比字符串长度多一个字节)
- 如果 precision 为 12(比字符串长度多几个字节)
还有“数组中的宽字符转换为多字节字符”。这是否意味着应该先将 UTF-16 转换为 UTF-8?如果我希望只使用 UTF-16,这很奇怪。
【问题讨论】:
-
%s接受一个字符串。由于所有空字节,您不能将 UTF-16 存储在 C 字符串中。 (另外,UTF-16 不是字符集;它是一种编码。) -
"\x54\x00\x45\x00\x53\x00\x54\x00"是一个长度为1的字符串,包含T。 -
你是专门问
%ls/wchar_t吗? -
CHAR_BIT在您的实现中的值是多少?如果CHAR_BIT == 8,则不能用%s处理UTF-16;您将使用%ls并传递wchar_t *作为相应的参数。然后,您必须阅读规范的第二段。如果CHAR_BIT == 16,则数据中的八位字节数不能为奇数。然后,您需要了解wchar_t与char的关系(它们的大小是否相同?它们是否具有相同的符号?)并解释这两个段落以产生统一的效果 - 除非您决定使用wchar_t表示 UTF-32。 -
@melpomene 当然可以,您只需要 16 位字符。