我使用的语言是C.
x和n的类型是int.
x和n的类型是int.
我有一个行代码如下
printf("x=%x,n=%d,first=%x,second=%x\n",x,n,((~(x+0xffffffff))>>n),((~x+1)>>n));
它显示了x,n的值和两个移位x的补数的n位的方法.
当x = 0x80000000时,〜(x 0xffffffff)= 0x8000000,~x 1 = 0x80000000,但当将这两个移位n位时,结果是不同的.
顺便说一句,如果我把0xffffffff改为~1 1(即〜(x(~11)),结果与~x 1相同
我想知道为什么会这样.谢谢.
解决方法
Pavan Manjunath现在删除的答案对于一个案例有正确答案,假设int像往常一样是32位类型.整数常量
0xffffffff
具有值2 ^ 32 – 1并且不能由int表示,但它可以表示为unsigned int.所以它的类型是unsigned int(6.4.4.1).因此,x被转换为unsigned int以进行加法,并且
((~(x+0xffffffff))>>n)
评估为
((~(0x80000000u + 0xffffffffu)) >> n) ((~0x7fffffffu) >> n) (0x80000000u >> n)
如果0 <= n <1,则值为2 ^(31-n) 32(如果n超出该范围,则为未定义的行为). 对于另一种情况,ouah的答案是正确的,当x = 0x80000000是int时,~0x8000000 = 0x7fffffff = INT_MAX和INT_MAX 1是未定义的行为,因为有符号整数溢出. 然而,常见的行为是环绕,然后加法的结果是有符号整数0x80000000,负整数的右移是实现定义的行为(6.5.7). Common正在使用符号扩展进行移位,这将产生结果-2 ^(31-n),然后通过printf转换说明符%将其解释为unsigned int,值为2 ^ 32 – 2 ^(31-n) X.