我正在努力确保我的UTF-8和UTF-16之间的转换代码在空终止符方面是正确的。
在MultiByteToWideChar()
的情况下,我理解如果您将输出缓冲区大小设置为0,则会获得字符数<包含终止空值。我的问题是:您是否将计数包括终止空值作为新的缓冲区大小,并与计数包括终止空值进行比较?或者换句话说,这是正确的吗?
n = MultiByteToWideChar(..., NULL, 0);
if (MultiByteToWideChar(..., buf, n) != n) error();
我猜测输入缓冲区大小下的模糊
如果此参数设置为正整数,则该函数将精确处理指定的字节数。如果提供的大小不包含终止空字符,则生成的Unicode字符串不以空值终止,并且返回的长度不包括此字符。
,输入缓冲区大小为-1,答案是肯定的;是这样吗?
对于WideCharToMultiByte()
,我根本不确定null终止符。如果我为输出缓冲区计数传递0,返回的计数是否包含空终止符?对于实际转换,我是否说输出缓冲区的大小包括空终止符?返回值是否包含空终止符?
我当前的代码用no,no和no(分别)回答这些。这似乎有效,但我宁愿不相信那些偶然起作用的代码。我的唯一提示是以下模糊:
如果此参数为-1,则该函数处理整个输入字符串,包括终止空字符。因此,生成的字符串具有终止空字符,函数返回的长度包括该字符。
所以我认为答案真的是肯定的,是的,是的,但我还是不完全确定。
感谢。
为了更好的衡量,这是我的代码:
// note: assume logLastError() calls DebugBreak() and that uiAlloc() aborts on failure
#define MBTWC(str, wstr, bufsiz) MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, bufsiz)
WCHAR *toUTF16(const char *str)
{
WCHAR *wstr;
int n;
n = MBTWC(str, NULL, 0);
if (n == 0)
logLastError("error figuring out number of characters to convert to in toUTF16()");
wstr = (WCHAR *) uiAlloc(n * sizeof (WCHAR), "WCHAR[]");
// TODO verify return includes null terminator
if (MBTWC(str, wstr, n) != n)
logLastError("error converting from UTF-8 to UTF-16 in toUTF16()");
return wstr;
}
#define WCTMB(wstr, str, bufsiz) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, bufsiz, NULL, FALSE)
char *toUTF8(const WCHAR *wstr)
{
char *str;
int n;
n = WCTMB(wstr, NULL, 0);
if (n == 0)
logLastError("error figuring out number of characters to convert to in toUTF8()");
// TODO does n include the null terminator?
str = (char *) uiAlloc((n + 1) * sizeof (char), "char[]");
if (WCTMB(wstr, str, n + 1) != n)
logLastError("error converting from UTF-16 to UTF-8 in toUTFF8()");
return str;
}
答案 0 :(得分:1)
MultiByteToWideChar
返回值的文档说:
如果函数成功且cchWideChar为0,则返回值是lpWideCharStr指示的缓冲区所需的大小(以字符为单位)。
那么,对你的问题。
如果我为输出缓冲区计数传递0,返回的计数是否包含空终止符?
是的,如果您将-1
传递给cbMultiByte
。如果你通过了strlen(lpMultiByteStr)
,那就没有。
对于实际转换,我是否说输出缓冲区的大小是否包含空终止符?
如果您希望缓冲区以空值终止,则为“是”,否则为“否”。
所以,完成了:
n = MultiByteToWideChar(..., -1, NULL, 0);
如果您希望缓冲区以空值终止,则可以选择分配长度为n
的缓冲区;如果您不希望以空值终止,则可以选择分配长度为n-1
的缓冲区。显然,您需要将n
或n-1
作为cchWideChar
参数传递,以匹配缓冲区的实际长度。
查看代码,很清楚您要创建以null结尾的缓冲区。您的toUTF16
代码是正确的。您的toUTF8
代码不是。您应该使用与toUTF16
中相同的长度处理代码。更重要的是,WideCharToMultiByte
的最终参数有点不精确。它是指向布尔值的指针。代码应该是:
#define WCTMB(wstr, str, bufsiz) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, bufsiz, NULL, NULL)
char *toUTF8(const WCHAR *wstr)
{
char *str;
int n;
n = WCTMB(wstr, NULL, 0);
if (n == 0)
logLastError("error figuring out number of characters to convert to in toUTF8()");
str = (char *) uiAlloc(n * sizeof (char), "char[]");
if (WCTMB(wstr, str, n) != n)
logLastError("error converting from UTF-16 to UTF-8 in toUTFF8()");
return str;
}