c - 从 WCHAR 转换为 char 时,为什么会出现额外的空终止字符?

标签 c winapi

我正在使用此 C 代码研究字符串的空终止。

#include <Windows.h>
#include <stdio.h>

int wmain(int argc, WCHAR *argv[])
{
    WCHAR *wstr = argv[1];
    int wlen, len, written;
    char *strA;
    DWORD nOut = 0;

    wlen = lstrlenW(wstr);

    printf("wlen: %d\n", wlen);

    if (wstr[wlen] == 0) printf("wstr[%d] == 0\n", wlen);
    if (wstr[wlen + 1] == 0) printf("wstr[%d] == 0\n", wlen + 1);

    len = WideCharToMultiByte(GetConsoleOutputCP(), 0, wstr, wlen, NULL, 0, NULL, NULL);
    printf("len: %d chars required\n", len);

    strA = HeapAlloc(GetProcessHeap(), 0, len + 1);
    if (!strA) return -1;

    written = WideCharToMultiByte(GetConsoleOutputCP(), 0, wstr, wlen, strA, len, NULL, NULL);
    printf("written: %d\n", written);
    strA[len] = 0; /* Null terminate the ASCII string */

    WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), strA, len, &nOut, NULL); printf("\n");

    if (strA[len] == 0) printf("strA[%d] == 0\n", len);
    if (strA[len + 1] == 0) printf("strA[%d] == 0\n", len + 1);

    HeapFree(GetProcessHeap(), 0, strA);

    return 0;
}

如果我提供由偶数个 WCHAR 组成的输入字符串,例如你好!,我明白:

wlen: 6
wstr[6] == 0
wstr[7] == 0 /* Where does this come from? */
len: 6 chars required
written: 6
Hello!
strA[6] == 0
strA[7] == 0 /* Where does this come from? */

但是如果我提供一个包含奇数个 WCHAR 的字符串,例如你好,我只得到:

wlen: 5
wstr[5] == 0
len: 5 chars required
written: 5
Hello
strA[5] == 0

为什么在wstr[len+1]str[len+1]处有一个额外的空终止符?据我所知,没有为 ASCII 字符串中的第二个 NUL 分配足够的内存。

最佳答案

strA = HeapAlloc(GetProcessHeap(), 0, len + 1);

strA[i] 的有效索引 i 包括 0len。这意味着读取 strA[len + 1] 会调用未定义的行为,因为您正在读取超出缓冲区末尾的内容。

当您调用未定义的行为时,任何事情都可以发生。一种可能的结果是,您的未定义行为导致您读取值为 0char

同样,此后

wlen = lstrlenW(wstr);

您知道 wstr[i] 的有效索引 i 包括 0wlen。因此,读取 wstr[wlen + 1] 又是一个错误。

简单地说,停止读取超出缓冲区末尾的内容。

您向 WideCharToMultiByte 传递了错误的长度值。应该是:

UINT cp = GetConsoleOutputCP();
len = WideCharToMultiByte(cp, 0, wstr, -1, NULL, 0, NULL, NULL);

written = WideCharToMultiByte(cp, 0, wstr, -1, strA, len+1, NULL, NULL);

关于c - 从 WCHAR 转换为 char 时,为什么会出现额外的空终止字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28761753/

相关文章:

c++ - 为什么结构体的 sizeof 不等于每个成员的 sizeof 之和?

C 标准版本检查

c - 为什么我的 float 被截断了?

c++ - 使用 ListView 对表格进行排序

c++ - 重新注册用户定义的窗口类 - C++

c - 将指针字符打印为十六进制

c - 如何通过串行读取在 Arduino LCD 上存储两条单独的线

windows - 我有翻译 Windows Winapi/Win32/系统错误消息的 Microsoft 资源吗?

javascript - 如何将 OVERLAPPED 结构转换为 js-ctypes?

c++ - Qt 需要将 Qt 应用程序带到前台,从 win32 应用程序调用