为什么wstring可以接受WCHAR []而字符串不接受UCHAR []

时间:2016-06-25 08:34:41

标签: c++

我正在尝试打印NtQueryValueKey的{​​{1}}返回值UCHAR Data[1];我已经尝试printfcoutstring(Data, DataLengh),前两个仅打印1个字符,最后一个字符抛出异常...基本上,如果我将数据类型更改为WCHAR Data[1]并使用wstring(Data),它会正常接受它而不会抱怨...也wprintf正常打印值。

编辑:我的意思是NtQueryValueKey使用KEY_VALUE_PARTIAL_INFORMATION,我正在使用VS 2015 btw ......

2 个答案:

答案 0 :(得分:1)

你必须混淆一些东西。您没有指定用于第二个参数的KEY_NAME_INFORMATION枚举中的值来指定数据类型,但快速查看MSDN会显示所有结构都包含WCHAR Name[1];或类似于最后一个成员(我猜是你感兴趣的那个)。您是否可以详细说明并提供说明您实际需要使用UCHAR的文档的链接或其他方法?

答案 1 :(得分:0)

WCHARwchar_t的别名。 std::wstring使用wchar_t个元素进行操作。 WCHAR[]可以衰减到wchar_t*,因此可以直接分配到std::wstring

UCHARunsigned char的别名。 std::string代替char元素运行。如果没有UCHAR[]的类型转换,则UCHAR* / std::string无法直接分配给char*,因为charunsigned char是不同的数据类型。

unsigned char通常用于表示8位字节(与BYTE使用的数据类型相同)。

NtQueryKey()使用WCHAR[]字符数组将字符串作为UTF-16LE编码的字节返回,而不是UCHAR[]字节数组。因此,如果您使用UCHAR[]开头,那么您的代码就会声明错误。但即便如此,如果您注意编码和字节长度,可以使用UCHAR,并使用适当的类型转换。

Length报告的任何关联NtQueryKey()值都以字节为单位,而不是字符。 sizeof(UCHAR)为1,sizeof(WCHAR)为2.因此每2 UCHAR代表1 WCHAR。并且字符串不会以空值终止,因此您在打印或转换时必须考虑Length

在基于拉丁语的语言中,最常用的Unicode字符将是< = U + 00FF,因此UTF-16LE中的每个其他UCHAR通常都是0.这在UTF时被解释为空终止符-16打印有printf()std::cout。您需要改为使用wprintf()std::wcout

Data转换为std::string是有效的操作,不应引发异常:

std::string((char*)Data, DataLength)

提供:

  • Data是一个有效的指针。

  • DataLength是准确的字节数。

这可能引发异常的唯一方法是:

  • Data未指向有效内存。

  • DataLength的值大于为Data分配的实际字节数。

  • 可用内存太低,无法分配std::string的内部缓冲区。

  • 内存已损坏。

Data单独分配给std::wstring而不考虑DataLength不是有效操作,因为字符串不是以空值终止的。您必须指定长度:

std::wstring(Data, DataLength / sizeof(WCHAR))

如果DataUCHAR,则使用类型代码:

std::wstring((WCHAR*)Data, DataLength / sizeof(WCHAR))

使用Data直接打印wprintf()时,您必须将DataLength作为输入参数传递:

wprintf(L"%.*s", DataLength / sizeof(WCHAR), Data);

使用Data直接打印std::wcout时,您应使用write()代替operator<<,以便将DataLength作为输入参数传递:

std::wcout.write(Data, DataLength / sizeof(WCHAR));

如果DataUCHAR,则使用类型代码:

std::wcout.write((WCHAR*)Data, DataLength / sizeof(WCHAR));