【发布时间】:2014-08-28 10:34:53
【问题描述】:
我有一个存储 1 字节十六进制字符的 unsigned char 数组,我想对这些值进行按位运算。
在使用 reinterpret_cast 将它们变成一个字符串后(考虑使用 std::stringstream 和 std::bitset 进行必要的操作),我尝试打印字符串以查看内容是什么。相当奇怪的是,我注意到 std::cout 没有给出预期的结果,但是使用 printf 做到了!
这是一个简单的例子:
int main(int argc, char *argv[])
{
unsigned char my_txt[] = {
0x52, 0x5f, 0x73, 0x68, 0x7e, 0x29, 0x33, 0x74, 0x74, 0x73, 0x72, 0x55
};
unsigned int my_txt_len = 12;
std::string my_std_string(reinterpret_cast<const char *>(my_txt), my_txt_len);
for (size_t i=0;i<my_txt_len;i++)
printf("%02X ", my_std_string[i]); // Works fine!
printf("\n");
std::cout << my_std_string << std::endl; // Bad stuff happens :S
return 0;
}
有输出:
52 5F 73 68 7E 29 33 74 74 73 72 55 // Expected
R_sh~)3ttsrU // ??
决心找到解决方案,我修补了一段时间 - 猜测 reinterpret_cast 可能会导致这种行为。我最终发现这样做:
std::cout << std::hex << (int)my_std_string[0] << std::dec << std::endl;
产生了预期的结果,至少对于第一个字符。遍历一个循环也为其他 11 个字节提供了正确的值。
有人可以解释为什么 std::cout 会发生这种情况而不是 printf 吗?起初,我认为也许我需要将其转换回unsigned char,但这样做没有任何效果。为什么转换为 int 会给出正确的输出?
在使用 reinterpret_cast 之后对存储在字符串中的值进行按位运算是否安全?我突然想到,所有这些都可能毫无意义,因为我相信我可以直接对 unsigned char 进行二进制数学运算,不是吗?我们将不胜感激。
对于那些好奇的人,我正在尝试编写一个自定义 C++ 控制台应用程序(Windows 7 64 位计算机上的 Microsoft Visual Studio 2010),以使用供应商的 API 与 CAN-USB 适配器接口。我希望接收(作为较大的“接收帧”结构的一部分)8 字节无符号字符数组,其值为十六进制,我需要处理这些值以获得我的应用程序可用的数据。然后将处理后的数据存储在协议缓冲区中,以便在 matlab 中进一步解释。
抱歉,这似乎是一个愚蠢的问题 - 我来自硬件背景,并且有一段时间没有进行任何认真的编程(SO 上的第一篇文章!)。
【问题讨论】:
-
您期望的字符串是什么?根据 ascii 表,这似乎是正确的。
-
您不存储“1 字节十六进制字符”。您存储字节。您在文字中写入以将这些值输入程序源代码的数字的基数不相关。此外,您的
printf和std::cout方法甚至不完全相同,因此抱怨它们有不同的结果似乎对所讨论的编程语言有些不公平。 -
感谢@LightnessRacesinOrbit 和milleniumbug。是的,看来我对基础知识有点生疏了哈哈所以我认为对存储在字符串中的值进行二进制数学运算(位掩码、将字节相加等)是安全的?
-
@KnightsValour:当然为什么不呢?
标签: c++ cout stdstring reinterpret-cast