Winapi 这些是MultiByteToWideChar()和WideCharToMultiByte()的空终止符规则吗?我不知道';我不太懂MSDN

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()

我试图确保我的代码在UTF-8和UTF-16之间转换时,对于空终止符是正确的

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没有捕捉到这一点。。。