我对位移后的否定操作感到困惑。 例如:
-(1<<7) is 0xffffff80
但为什么最重要的位填充1?
我对操作-
的含义感到困惑。
编辑1:我使用printf("%#08x\n", -(1<<7))
打印出值。
答案 0 :(得分:2)
首先,谢谢你提出这个问题。编写测试程序以说明您不确定的内容通常是个好主意,然后尝试不同的东西来弄清楚细节。
评论,就像UB一样,通常不准确。在这种情况下,所发生的事情是非常可预测和合理的,正是有经验的程序员应该期待的。
我在Eclipse / Microsoft C编译器上运行了以下代码:
#include <stdio.h>
main()
{
int i;
unsigned int j;
i = -(1<<7);
printf("%i\n", i);
printf("%08x\n", i);
j = -(1<<7);
printf("%u\n", j);
printf("%08x\n", j);
}
得到以下输出:
-128
ffffff80
4294967168
ffffff80
这是预期的,因为:(1 <7)等于128并且 - (128)是-128。 i的内容的printf
完全以二进制形式生成了-128的值。
看到这个的方法是采用2的补码ffffff80 = 0000007f + 1 = 00000080,二进制为128。因此,您可以看到,取一个数的2的补码是我们如何取整数的负数。
真正的大数字是相同内容的无符号值。
尽可能写一些代码来检查内容是如何工作的!
答案 1 :(得分:0)
减号运算符(实现已定义,但最有可能)将在其参数上执行二进制补码(在本例中为十进制128)。 2的补码是:减1并反转所有位。
答案 2 :(得分:0)
有效位用1填充,因为它们代表符号,重复它们不会影响值。对于正数, 10 和 010 和 0000010 都是相等的。并且由于 1 的最重要位表示负数,因此在负数前面放置尽可能多的1并不会影响幅度。你可以使用2s补码算法检查这个事实。
答案 3 :(得分:0)
-(1<<7)
不是0xffffff80
。 1<<7
是第7次幂的1倍2,即128.所以-(1<<7)
是-128。您将其视为0xffffff80
的原因最可能的解释是,您通过将其传递给printf
来调用未定义的行为,以便与%x
格式说明符一起使用。 %x
采用unsigned int
参数(只要值为非负值,也可以采用带符号的int
)但是您传递的参数类型为int
,是否定的。因此,会导致未定义的行为。
答案 4 :(得分:0)
答案非常简单,其结果来自于如何在计算机内存中保存多个数字。
我猜你很明显1&lt;&lt; 7意味着。它等于128.你的“ - ”符号只表示你想改变结果的te符号,所以最终的结果是-128。
但为什么你会有所不同呢?这是答案:
通常有两种类型的变量:有符号和无符号。 两种类型都保存在momory中,实际上不知道哪种类型开始使用。程序员可以知道存储了哪种号码。
当您将变量声明为无符号时,它可以存储从0到n的值,其中n是特定类型变量的最大值。
使用带符号的值时,可以存储定义的负值中的值,直到某个定义的正值。
使用无符号变量时,计算值非常简单。 请考虑一个8位(1字节)无符号变量的简单示例:
如前所述,最小值为0,当设置了所有8位时,最大值为255.
对于签名类型的变量,正在使用特殊格式: 从0到127的数字的保存方式与无符号类型相同。并且127的值是8位变量的最大值。最小值为-128,存储为0b10000000或0x80。下一个是-127并保存为0b10000001或0x81,依此类推。最大的负数为-1,保存为0b11111111或0xFF。
因此,如果你有一个字节值0xff,它可以是:255(无符号时)或-1(有符号时)。 这里用于签名类型的变量的符号称为U2 - 请阅读此内容。
在您的特定情况下,您看起来有一个已签名(-128)的值,该值被视为无符号值。在你的情况下,使用32位(4字节)变量(可能(无符号)int),因此它看起来有点不同(结果更长),但你可能会看到一些相似性:U2中-128的最后两位数字无论用多少位来存储该值,系统总是为0x80。