Visual Studio 2015 的 UTF-16 编码字符串的内存布局是什么?
What's the memory layout of UTF-16 encoded strings with Visual Studio 2015?
WinAPI 使用 wchar_t
缓冲区。据我了解,我们需要使用 UTF-16 将所有参数编码为 WinAPI。
我们有两个版本的 UTF-16:UTF-16be
和 UTF-16le
。让我们编码一个字符串 "Example" 0x45 0x78 0x61 0x6d 0x70 0x6c 0x65
。使用 UTF-16be 字节应该这样放置:00 45 00 78 00 61 00 6d 00 70 00 6c 00 65
。对于 UTF-16le,它应该是 45 00 78 00 61 00 6d 00 70 00 6c 00 65 00
。 (我们省略了 BOM)。同一个字符串的字节表示不同
根据文档 Windows 使用 UTF-16le
。这意味着我们应该使用 UTF-16le 对所有字符串进行编码,否则它将不起作用。
同时,我的编译器 (VS2015) 使用 UTF-16be
作为我硬编码到我的代码中的字符串(类似于 L"my test string"
)。但是 WinAPI 可以很好地处理这些字符串。为什么有效?我错过了什么?
更新 1:
为了测试硬编码字符串的字节表示,我使用了以下代码:
std::string charToHex(wchar_t ch)
{
const char alphabet[] = "0123456789ABCDEF";
std::string result(4, ' ');
result[0] = alphabet[static_cast<unsigned int>((ch & 0xf000) >> 12)];
result[1] = alphabet[static_cast<unsigned int>((ch & 0xf00) >> 8)];
result[2] = alphabet[static_cast<unsigned int>((ch & 0xf0) >> 4)];
result[3] = alphabet[static_cast<unsigned int>(ch & 0xf)];
return std::move(result);
}
Little endian或big endian描述了8位以上的变量在内存中的存储方式。您设计的测试不测试内存布局,它直接使用 wchar_t
类型;整数类型的高位总是高位,无论 CPU 是大端还是小端!
对您的代码的这种修改将显示它的实际工作原理。
std::string charToHex(wchar_t * pch)
{
const char alphabet[] = "0123456789ABCDEF";
std::string result;
unsigned char * pbytes = static_cast<unsigned char *>(pch);
for (int i = 0; i < sizeof(wchar_t); ++i)
{
result.push_back(alphabet[(pbytes[i] & 0xf0) >> 4];
result.push_back(alphabet[pbytes[i] & 0x0f];
}
return std::move(result);
}
WinAPI 使用 wchar_t
缓冲区。据我了解,我们需要使用 UTF-16 将所有参数编码为 WinAPI。
我们有两个版本的 UTF-16:UTF-16be
和 UTF-16le
。让我们编码一个字符串 "Example" 0x45 0x78 0x61 0x6d 0x70 0x6c 0x65
。使用 UTF-16be 字节应该这样放置:00 45 00 78 00 61 00 6d 00 70 00 6c 00 65
。对于 UTF-16le,它应该是 45 00 78 00 61 00 6d 00 70 00 6c 00 65 00
。 (我们省略了 BOM)。同一个字符串的字节表示不同
根据文档 Windows 使用 UTF-16le
。这意味着我们应该使用 UTF-16le 对所有字符串进行编码,否则它将不起作用。
同时,我的编译器 (VS2015) 使用 UTF-16be
作为我硬编码到我的代码中的字符串(类似于 L"my test string"
)。但是 WinAPI 可以很好地处理这些字符串。为什么有效?我错过了什么?
更新 1:
为了测试硬编码字符串的字节表示,我使用了以下代码:
std::string charToHex(wchar_t ch)
{
const char alphabet[] = "0123456789ABCDEF";
std::string result(4, ' ');
result[0] = alphabet[static_cast<unsigned int>((ch & 0xf000) >> 12)];
result[1] = alphabet[static_cast<unsigned int>((ch & 0xf00) >> 8)];
result[2] = alphabet[static_cast<unsigned int>((ch & 0xf0) >> 4)];
result[3] = alphabet[static_cast<unsigned int>(ch & 0xf)];
return std::move(result);
}
Little endian或big endian描述了8位以上的变量在内存中的存储方式。您设计的测试不测试内存布局,它直接使用 wchar_t
类型;整数类型的高位总是高位,无论 CPU 是大端还是小端!
对您的代码的这种修改将显示它的实际工作原理。
std::string charToHex(wchar_t * pch)
{
const char alphabet[] = "0123456789ABCDEF";
std::string result;
unsigned char * pbytes = static_cast<unsigned char *>(pch);
for (int i = 0; i < sizeof(wchar_t); ++i)
{
result.push_back(alphabet[(pbytes[i] & 0xf0) >> 4];
result.push_back(alphabet[pbytes[i] & 0x0f];
}
return std::move(result);
}