我知道〜操作符不能操作。但我无法弄清楚以下程序的输出(-65536)。究竟发生了什么?
#include <stdio.h>
int main(void) {
int b = 0xFFFF;
printf("%d",~b);
return 0;
}
答案 0 :(得分:9)
假设32位整数
int b = 0xFFFF; => b = 0x0000FFFF
~b = 0xFFFF0000
现在设置了最高位。假设2s complement,这意味着我们有一个负数。反转其他位然后添加一位会产生0x00010000
或65536
答案 1 :(得分:4)
将16位值0xffff
分配给32位整数b
时,变量b
实际上变为0x0000ffff
。这意味着当您执行按位补码时,它变为0xffff0000
,这与十进制-65536
相同。
答案 2 :(得分:2)
它正在做一个按位补充,这个输出可以帮助你更好地理解发生了什么:
std::cout << std::hex << " b: " << std::setfill('0') << std::setw(8) << b
<< " ~b: " << (~b) << " -65536: " << -65536 << std::endl ;
我收到的结果如下:
b: 0000ffff ~b: ffff0000 -65536: ffff0000
所以我们将低16位设置为1
,这给了我们0000ffff
然后我们做一个补码,将低16位设置为0
,将高16位设置为1
给了我们ffff0000
,它等于十进制的-65536
。
在这种情况下,由于我们正在使用按位运算,因此检查十六进制数据可以让我们深入了解正在发生的事情。
答案 3 :(得分:1)
C ++中的〜运算符是按位NOT运算符。它也称为按位补码。这会翻转已签名整数的位。
例如,如果你有
int b = 8;
// b in binary = 1000
// ~b = 0111
这将翻转代表提供的初始整数值的位。
答案 4 :(得分:1)
结果取决于您的平台上的签名整数的表示方式。最常见的表示是使用“2s补码”算法表示负值的32位值。也就是说,负值-x
由与无符号值2^32 - x
相同的位模式表示。
在这种情况下,原始位模式设置了低16位:
0x0000ffff
按位否定清除这些位并设置高16位:
0xffff0000
将此解释为负数会得到值-65536
。
通常,当你搞乱按位运算时,你会想要使用无符号类型,以避免这种混淆。
答案 5 :(得分:0)
您的评论:
如果它不是'b'..那么输出应为0,但为什么-65536
建议你期待以下结果:
uint32_t x = 0xFFFF;
uint32_t y = ~x;
是0
。
对于逻辑非操作,情况确实如此:
uint32_t x = 0xFFFF;
uint32_t y = !x;
...但operator~
不是逻辑 NOT,而是按位不是。有很大的不同。
对于非0值,逻辑返回0(对于真值,返回false),对于0值,返回1。
但是,按位不会反转给定值中的每个位。所以二进制NOT 0xF
:
0x0F: 00000000 11111111
~0x0F: 11111111 00000000
不是零,而是0xF0。
答案 6 :(得分:-1)
对于整数中的每个二进制数,按位NOT运算将所有1都变为0,并且所有0都变为1。
所以十六进制0xFFFF
是二进制1111 1111 1111 1111
(每个十六进制字符是4位,F,15,在所有四位中都是1s)
你设置一个32位整数,这意味着现在:
0000 0000 0000 0000 1111 1111 1111 1111
然后你没有,这意味着它是:
1111 1111 1111 1111 0000 0000 0000 0000
最高位是签名位(无论是正数还是负数),因此它给出一个负数。