当x=0x80000000时, ~(x-1) 和 ~x+1 的区别是什么?

7

我使用的编程语言是C。

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+(~1+1))),结果与~x+1相同。

我想知道为什么会出现这种情况。谢谢。


“(uint16_t) -1” 是可移植的 C 代码吗? - Lundin
@Lundin 那篇文章是错的。如果实现在 stdint.h 中提供了该类型,则标准保证 (uint16_t)-1 会产生 0xFFFF。当然,如果是你自己的 typedef,就没有任何保证了。没有歧义,固定宽度类型要求没有填充位,因此它甚至不仅限于值位(好吧,因为在 uintN_t 中只有值位,所以它确实是)。 - Daniel Fischer
3个回答

4
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 < 32,则值为2^(31-n)(如果n超出此范围,则行为未定义)。

对于另一种情况,ouah的答案是正确的,当x = 0x80000000是一个int时,~0x8000000 = 0x7fffffff = INT_MAX,而INT_MAX + 1是有符号整数溢出的未定义行为。

然而,常见的行为是环绕,然后加法的结果是有符号整数0x80000000,负整数的右移是实现定义的行为(6.5.7)。常见的是带符号扩展的移位,这将产生结果-2^(31-n),然后由printf转换说明符%x将其解释为unsigned int,其值为2^32 - 2^(31-n)


0 可以表示为 int,因此 ~0 的类型也是 int - Daniel Fischer

1
当x=0x80000000时,~(x+0xffffffff)=0x8000000,~x+1=0x80000000。
在一个32位int类型的系统上(假设x是int类型),采用二进制补码表示法,这个表达式:
 ~x+1

是未定义行为。x = 0x80000000 意味着 ~x == 0x7FFFFFFF == INT_MAX,而 INT_MAX + 1 是未定义行为。因此,~x + 1 可以是 0x80000000 或其他任何值。

这个表达式:

~(x+0xffffffff)

另一方面被定义为(在C中,0xffffffff是无符号整数)并且等于0x80000000。它实际上是被定义的,因为0xffffffff是一个无符号整数,在C标准的意义下,无符号整数永远不会溢出。

这意味着这个语句:

printf("x=%x,n=%d,first=%x,second=%x\n",x,n,((~(x+0xffffffff))>>n),((~x+1)>>n));

调用未定义的行为,比较两个结果毫无意义。


0

(假设sizeof(int)为4,即32位有符号值)。 0x80000000; // -2147483648是最小的可能负整数 0xFFFFFFFF // 是-1

将两者相加会导致从负数到正数的“环绕” 0x7FFFFFFF是两个数的和(使用int算术),即2147483647

在0x7FFFFFFF上使用“~”运算符会产生一个按位补码,或者0x80000000

如果你从任何int值开始,然后从中减去1(或者加上1,没有关系)足够多次,就会导致它翻转其符号。这是使用固定精度进行算术的基本问题。

在你的情况下,你不能指望混合使用有符号算术和位运算符而不非常注意这个限制性情况。

还要注意,在使用2的补码算术时存在一种不对称性:负数比正数多一个(因为你需要表示零,这样留下了其他值的奇数个位表示)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接