为什么 C/C++ 按位异或运算符关心符号?
Why does the C/C++ bitwise XOR operator care about sign?
一段时间以来,我一直在努力处理一些低级别的消息传递,结果证明这是校验和计算的问题。我认为按位 XOR 运算符不关心符号,所以我使用 QByteArray
来存储字节,并使用 at
方法,即 returns a char
, 来计算校验和。这些消息有时会得到适当的确认,但并非总是如此。
看起来另一端的人正在使用 uint8_t
来存储字节,并且
校验和在某些情况下失败。我通过将 char
转换为 uint8_t
来解决它,但我对此感到非常困惑。
为什么按位异或运算符关心符号?我认为它在位层面上起作用,不管它们代表什么。这是我用来尝试理解它的一段代码。
#include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <bitset>
int main ()
{
uint8_t a = 0b10010101;
char b = 0b10010101;
uint32_t checksum;
checksum = 55;
checksum ^= a;
std::cout << std::bitset<32>(checksum) << std::endl;
checksum = 55;
checksum ^= b;
std::cout << std::bitset<32>(checksum) << std::endl;
}
即使两个整数都包含相同的位,运算在每种情况下都会产生不同的结果。
首先你必须记住,如果 char
是有符号或无符号的,它是实现定义的。
那么你必须记住像char
或uint8_t
这样的较小类型的值在使用时是promoted到int
(或者可能是unsigned int
)在表达式中。此促销带来 签名扩展 签名类型。
因此,如果 char
有符号,值 0b10010101
将被提升为 0b11111111111111111111111110010101
(使用 two's complement 表示负数)。 与无符号值0b00000000000000000000000010010101
非常不同。
一段时间以来,我一直在努力处理一些低级别的消息传递,结果证明这是校验和计算的问题。我认为按位 XOR 运算符不关心符号,所以我使用 QByteArray
来存储字节,并使用 at
方法,即 returns a char
, 来计算校验和。这些消息有时会得到适当的确认,但并非总是如此。
看起来另一端的人正在使用 uint8_t
来存储字节,并且
校验和在某些情况下失败。我通过将 char
转换为 uint8_t
来解决它,但我对此感到非常困惑。
为什么按位异或运算符关心符号?我认为它在位层面上起作用,不管它们代表什么。这是我用来尝试理解它的一段代码。
#include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <bitset>
int main ()
{
uint8_t a = 0b10010101;
char b = 0b10010101;
uint32_t checksum;
checksum = 55;
checksum ^= a;
std::cout << std::bitset<32>(checksum) << std::endl;
checksum = 55;
checksum ^= b;
std::cout << std::bitset<32>(checksum) << std::endl;
}
即使两个整数都包含相同的位,运算在每种情况下都会产生不同的结果。
首先你必须记住,如果 char
是有符号或无符号的,它是实现定义的。
那么你必须记住像char
或uint8_t
这样的较小类型的值在使用时是promoted到int
(或者可能是unsigned int
)在表达式中。此促销带来 签名扩展 签名类型。
因此,如果 char
有符号,值 0b10010101
将被提升为 0b11111111111111111111111110010101
(使用 two's complement 表示负数)。 与无符号值0b00000000000000000000000010010101
非常不同。