我正在尝试使用 iconv(3) 使用下面的代码将宽字符串转换为 UTF-8。当我运行以下命令时,iconv 调用返回 E2BIG,就好像输出缓冲区中没有足够的可用空间字节一样。尽管(我认为)我已经调整了输出缓冲区的大小以承认 UTF-8 的最坏情况扩展,但还是会发生这种情况。事实上,假设输入是一个简单的 ASCII 'A',编码为 wchar_t 后跟零 wchar_t 终止符,输出应该正好是两个字节/字符:一个 'A' 后跟一个 '\0'。
我的 Linux 系统上的“man utf-8”表示 UTF-8 字节序列的最大长度为 6 个字节,所以我相信对于 2 个 wchar_ts(一个字符后跟空终止符)的输入缓冲区,使(在我的系统)总共 8 个字节(因为 sizeof(wchar_t) == 4),12 个字节的缓冲区(2 * UTF8_SEQUENCE_MAXLEN)应该足够了。
通过实验,如果我将 UTF8_SEQUENCE_MAXLEN 增加到 16,iconv 的返回值表示成功(15 仍然失败)。但是我看不到任何 wchar_t 值在以 UTF-8 编码时会占用这么多字节的任何方式。
我的计算有问题吗?16 字节的 UTF-8 序列是否可能?我做错了什么?
#include <stdio.h>
#include <stdlib.h>
#include <iconv.h>
#include <wchar.h>
#define UTF8_SEQUENCE_MAXLEN 6
/* #define UTF8_SEQUENCE_MAXLEN 16 */
int
main(int argc, char **argv)
{
wchar_t *wcs = L"A";
signed char utf8[(1 /* wcslen(wcs) */ + 1 /* L'\0' */) * UTF8_SEQUENCE_MAXLEN];
char *iconv_in = (char *) wcs;
char *iconv_out = (char *) &utf8[0];
size_t iconv_in_bytes = (wcslen(wcs) + 1 /* L'\0' */) * sizeof(wchar_t);
size_t iconv_out_bytes = sizeof(utf8);
size_t ret;
iconv_t cd;
cd = iconv_open("WCHAR_T", "UTF-8");
if ((iconv_t) -1 == cd) {
perror("iconv_open");
return EXIT_FAILURE;
}
ret = iconv(cd, &iconv_in, &iconv_in_bytes, &iconv_out, &iconv_out_bytes);
if ((size_t) -1 == ret) {
perror("iconv");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}