我在c中有以下代码:
unsigned int a = 60; /* 60 = 0011 1100 */
int c = 0;
c = ~a; /*-61 = 1100 0011 */
printf("c = ~a = %d\n", c );
c = a << 2; /* 240 = 1111 0000 */
printf("c = a << 2 = %d\n", c );
第一个输出是-61而第二个输出是240.为什么第一个printf计算1100 0011的二进制补码而第二个只是将1111 0000转换为十进制等值?
答案 0 :(得分:6)
您假设int
只有8位宽。您的系统可能不是这种情况,int
可能使用16位或32位。
在第一个例子中,所有位都被反转。这实际上是一个直接的反转,而不是两个补充:
1111 1111 1111 1111 1111 1111 1100 0011 (32-bit)
1111 1111 1100 0011 (16-bit)
在第二个示例中,当您将其向左移动2时,最高位仍然为零。您通过在评论中将数字描述为8位来误导自己。
0000 0000 0000 0000 0000 0000 1111 0000 (32-bit)
0000 0000 1111 0000 (16-bit)
答案 1 :(得分:0)
尽量避免使用有符号整数进行按位运算 - 通常它会导致您进入未定义的行为。
这里的情况是您正在使用无符号值并将它们分配给已签名的变量。对于~60
,这是undefined behavior。您将其视为-61,因为位模式~60
也是-61的二进制补码表示。另一方面,60 << 2
出现正确,因为240
具有与有符号和无符号整数相同的表示。