Winapi 这些是MultiByteToWideChar()和WideCharToMultiByte()的空终止符规则吗?我不知道';我不太懂MSDN
我试图确保我的代码在UTF-8和UTF-16之间转换时,对于空终止符是正确的 在Winapi 这些是MultiByteToWideChar()和WideCharToMultiByte()的空终止符规则吗?我不知道';我不太懂MSDN,winapi,encoding,Winapi,Encoding,我试图确保我的代码在UTF-8和UTF-16之间转换时,对于空终止符是正确的 在MultiByteToWideChar()的情况下,我知道如果您传递的输出缓冲区大小为0,则会得到字符数,包括终止null。我的问题是:您是否将计数包括终止空值作为新的缓冲区大小传递,并与计数包括终止空值进行比较?或者换句话说,这是正确的吗 n = MultiByteToWideChar(..., NULL, 0); if (MultiByteToWideChar(..., buf, n) != n) error()
MultiByteToWideChar()
的情况下,我知道如果您传递的输出缓冲区大小为0,则会得到字符数,包括终止null。我的问题是:您是否将计数包括终止空值作为新的缓冲区大小传递,并与计数包括终止空值进行比较?或者换句话说,这是正确的吗
n = MultiByteToWideChar(..., NULL, 0);
if (MultiByteToWideChar(..., buf, n) != n) error();
我是从输入缓冲区大小下的简介中猜出来的
如果此参数设置为正整数,则函数将精确处理指定的字节数。如果提供的大小不包括以null结尾的字符,则生成的Unicode字符串不会以null结尾,并且返回的长度不包括此字符
输入缓冲区大小为-1,表示答案是肯定的;是这样吗
对于WideCharToMultiByte()
,我对空终止符一点也不确定。如果我为输出缓冲区计数传递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;
}
返回值的文档说明: 如果函数成功且cchWideChar为0,则返回值为LPWIDECHARST指示的缓冲区所需的大小(以字符为单位) 所以,请回答你的问题 如果我为输出缓冲区计数传递0,则返回的计数是否包含空终止符 是,如果您将
-1
传递给cbMultiByte
。如果通过了strlen(lpMultiByteStr),则为否
对于实际转换,我是说输出缓冲区的大小是否包含空终止符
如果希望缓冲区以null结尾,则为“是”;如果不希望缓冲区以null结尾,则为“否”
因此,在完成以下工作之后:
n = MultiByteToWideChar(..., -1, NULL, 0);
如果要终止缓冲区null,可以选择分配长度为n
的缓冲区,如果不希望终止缓冲区null,可以选择分配长度为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;
}
因此,返回值应该等于输出大小,并且
WideCharToMultiByte()
遵循相同的规则。谢谢还感谢您发现最后一个参数问题;我使用-Wall-Wextra
编译,我很惊讶gcc没有捕捉到这一点。。。