MultiByteToWideChar不能很好地转换我的字符串

Dav*_*aim 2 c++ unicode winapi

我正在构建一个合成的UTF-8字符串std::string并尝试将其转换为MultiByteToWideChar.这是我的代码:

std::string str;
str += 'A'; 
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
std::wstring wstr;

if (str.empty()){
    wstr = L"";
}
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
std::wstring wstrTo(sizeNeeded, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), &wstrTo[0], sizeNeeded);
wstr = wstrTo;

std::wcout << wstr; 
Run Code Online (Sandbox Code Playgroud)

事实证明,这MultiByteToWideChar并不是str简单地转向L"ABC"字符串,而是将每个字符转变为wchar_t- 意味着该对'A' + char(0)不会转向L'A'但是L'A' + L'\0'

我在这里做错了什么或这是预期的行为MultiByteToWideChar

Rem*_*eau 5

std::string str;
str += 'A'; 
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
Run Code Online (Sandbox Code Playgroud)

这不是产生UTF-8编码的字符串!它正在生成一个UTF-16编码的字符串.

int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
Run Code Online (Sandbox Code Playgroud)

您告诉MultiByteToWideChar()我们将原始字节解释str为UTF-8,即使它实际上没有以UTF-8编码.

Unicode代码点U+0000在UTF-8中有效(它被编码为0x00),因此每个0x00字符str都将被解释为代码点U+0000,其余字符将按原样解释,因为它们都小于U+0080.因此,"UTF-8"字符串中没有多字节序列,只有单字节序列.

最终得到wstring包含以下代码点的UTF-16 :

0x41 -> U+0041 
0x00 -> U+0000
0x42 -> U+0042
0x00 -> U+0000
0x43 -> U+0043
0x00 -> U+0000
0x00 -> U+0000
0x00 -> U+0000
Run Code Online (Sandbox Code Playgroud)

如果您str正确编码为UTF-8,然后将其解释为UTF-8,您最终会得到正确的UTF-16 wstring:

std::string str;
str += 'A'; 
str += 'B';
str += 'C';
str += char(0);
Run Code Online (Sandbox Code Playgroud)

0x41 -> U+0041 
0x42 -> U+0042
0x43 -> U+0043
0x00 -> U+0000
Run Code Online (Sandbox Code Playgroud)

或者,如果您将str编码保留为UTF-16并将其解释为UTF-16(您无法使用MultiByteToWideChar()它,则必须手动执行),您仍然会得到wstring包含正确代码点的UTF-16 :

std::string str;
str += 'A'; 
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
Run Code Online (Sandbox Code Playgroud)

0x41 0x00 -> U+0041 
0x42 0x00 -> U+0042
0x43 0x00 -> U+0043
0x00 0x00 -> U+0000
Run Code Online (Sandbox Code Playgroud)