我在维基百科和堆栈溢出中读到了两个补码,这是我理解的但是我不确定它是否正确
签署了
最左边的位被解释为-2 31 ,这就是我们如何得到负数
unsigned int
最左边的位被解释为+2 31 ,这就是我们如何实现大的正数
当我们存储3对-3时,编译器会看到什么?
我认为3总是00000000000000000000000000000011
和-3始终是11111111111111111111111111111101
C中3对-3的例子:
unsigned int x = -3;
int y = 3;
printf("%d %d\n", x, y); // -3 3
printf("%u %u\n", x, y); // 4294967293 3
printf("%x %x\n", x, y); // fffffffd 3
答案 0 :(得分:2)
二进制补码是一种用二进制表示负整数的方法。
首先,这是一个标准的32位整数范围:
Signed = -(2 ^ 31) to ((2 ^ 31) - 1)
Unsigned = 0 to ((2 ^ 32) - 1)
在二进制补码中,通过反转其正等效的位并加1来表示负数:
10 which is 00001010 becomes -10 which is 11110110 (if the numbers were 8-bit integers).
此外,二进制表示仅在您计划使用按位运算符时才很重要。 如果你做基本算术,那么这就不重要了。
这可能在上述时间之外产生意外结果的唯一时间是获得签名版本的 - (2 <&lt;&lt; 31)的绝对值,这将总是给出负数。
您的问题与表示无关,而与类型有关。 无符号整数中的负数表示相同,不同之处在于它变为超高数,因为它必须为正且符号位正常工作。
如果值为无符号等,您还应该意识到((2 ^ 32) - 5)与-5完全相同。
因此,以下情况属实:
unsigned int x = (2 << 31) - 5;
unsigned int y = -5;
if (x == y) {
printf("Negative values wrap around in unsigned integers on underflow.");
}
else {
printf( "Unsigned integer underflow is undefined!" );
}
答案 1 :(得分:1)
数字不会改变,只是对数字的解释。对于大多数二进制补码处理器,加法和减法执行相同的数学运算,但假设数字是无符号的,则设置进位/借位状态,假设数字是有符号的,则设置溢出状态。对于乘法和除法,有符号和无符号数之间的结果可能不同(如果一个或两个数字都是负数),因此存在乘法和除法的单独有符号和无符号版本。
答案 2 :(得分:1)
是的,你是对的,请允许我进一步解释,以便澄清。
int和unsigned int之间的区别在于如何解释这些位。机器以相同的方式处理无符号和有符号位,但是为签名添加了额外的位。在处理相关主题时,两个补码表示法非常易读。
示例:
The number 5's, 0101, inverse is 1011.
在C ++中,它取决于您何时应该使用每种数据类型。当函数或运算符返回这些值时,应使用无符号值。 ALU非常类似地处理有符号和无符号变量。
用二进制补码写的确切规则如下:
示例2(两个补码之美):
-2 + 2 = 0 is displayed as 0010 + 1110; and that is 10000. With overflow at the end, we have our result as 0000;
答案 3 :(得分:1)
对于32位整数,对于有符号和无符号数, n -th位总是解释为+2 n 。< / p>
对于设置了第31位的有符号数,结果由-2 32 调整。
实施例:
1111 1111 1111 1111 1111 1111 1111 1111
2 as unsigned int被解释为2 31 +2 30 + ... + 2 1 2 0 。将其解释为带符号的int将是相同的MINUS 2 32 ,即2 31 +2 30 + ... + 2 < sup> 1 +2 0 -2 32 = -1
。
(好吧,可以说对于带有第31位设置的有符号数字,这个位被解释为-2 31 而不是+2 31 ,就像你一样在问题中说。我发现这种方式不太清楚。)
您对3和-3的表示是正确的:3 = 0x00000003
, - 3 + 2 32 = 0xFFFFFFFD
。