我试图使用下面的代码将宽字符字符串转换为UTF-8:iconv(3)。当我运行下面的代码时,iconv调用返回E2BIG,好像输出缓冲区中没有足够的空间。尽管(我认为)我已经将输出缓冲区大小设置为接受UTF-8的最坏情况。事实上,考虑到输入仅是一个简单的ASCII编码为wchar_t的“A”,后跟一个零wchar_t终止符,输出应该正好是两个字节/字符:一个“A”后跟一个“\0”。
在我的Linux系统上,“man utf-8”说UTF-8字节序列的最大长度为6个字节,因此我认为对于2个wchar_t(一个字符和一个空终止符)的输入缓冲区,在我的系统上总共有8个字节(因为sizeof(wchar_t) == 4),一个12字节(2 * UTF8_SEQUENCE_MAXLEN)的缓冲区应该足够。
通过实验,如果我增加UTF8_SEQUENCE_MAXLEN到16,iconv的返回值表示成功(15仍然会失败)。但我无法看出任何wchar_t值在UTF-8编码时会占用那么多字节。
我的计算错了吗?16字节的UTF-8序列是可能的吗?我做错了什么?
在我的Linux系统上,“man utf-8”说UTF-8字节序列的最大长度为6个字节,因此我认为对于2个wchar_t(一个字符和一个空终止符)的输入缓冲区,在我的系统上总共有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;
}