首页 > 试题广场 >

以下代码的执行结果是().

[单选题]
以下代码的执行结果是().
#include<stdio.h>
int main(){
   int i = -2147483648;
   return printf("%d,%d,%d,%d", ~i, -i, 1 - i, -1 - i);
}
  • 0,2147483648,2147483649,2147483647
  • 0,-2147483648,-2147483647,2147483647
  • 2147483647,2147483648,2147483649,2147483647
  • 2147483647,-2147483648,-2147483647,2147483647
Green848的答案里面有些本质性的错误,只不过误打误撞刚好跟实际计算出来的答案一样而已。看来大家对原码、反码、补码、取反运算~、以及单目运算符 - 的理解还不够哈,O(∩_∩)O,相信细心的同学肯定回发现Green848的答案有这样一些问题:
首先,-2147483648这个数为32位int所能表示的最小负整数,而如果原码为 1000 0000  0000  0000  0000  0000  0000  0000(表示-0) ,其反码应为数值位取反,符号位不变,即1111  1111  1111  1111  1111  1111  1111  1111,
补码为反码+1 即为0 000 0000  0000  0000  0000  0000  0000  0000 (最高位溢出,舍去),
而+0 的原码、反码、补码均为 0 000 0000  0000  0000  0000  0000  0000  0000,
如果用 1000 0000  0000  0000  0000  0000  0000  0000作为 -2147483648的原码,则会导致 -2147483648和0的补码表示一样,因此,计算机中规定用 1000 0000  0000  0000  0000  0000  0000  0000来作为 -2147483648的补码,以确保-2147483648~2147483647都有唯一的补码表示;
总结以上内容:正数的原码、反码、补码形式一致,负数的反码为原码的数值位取反,补码为反码+1也即是原码的数值位取反再+1,计算机中以补码表示数据和运算,而32位最小负整数的补码为 1000 0000  0000  0000  0000  0000  0000  0000。
然后回到本道题目的解答:

首先,求 ~i , i的补码为1000 0000  0000  0000  0000  0000  0000  0000,取反0111 1111 1111 1111 1111 1111 1111 1111,此为补码,符号位为0,表示正数,正数原码补码一致,因而该数即表示231-1,即2147483647

然后,求 -i ,要对一个数值执行单目运算符 -  表示的是对该数取反然后再+1,也即是我们常说的求补运算,注意这里取反+1与原码求补码的区别!也就是求补运算与求补码是不一样的!例子(4位有符号整数):x=-4  1100(补码)   -x=~x+1 也即是 0011+0001=0100(4),而1100再求补码应是先数值位取反,即1011,然后+1,变成1100!注意这两者(求补与求补码)之间的区别。
题目中  i的补码为 1000 0000  0000  0000  0000  0000  0000  0000,取反+1,仍为 1000 0000  0000  0000  0000  0000  0000  0000,即    -2147483648

1-i  我们已经求出-i的补码为1000 0000  0000  0000  0000  0000  0000  0000 加上1的补码即为 1000 0000  0000  0000  0000  0000  0000  0001
该补码表示的原码为1 111 1111  1111 1111 1111 1111 1111 1111,即为- 2147483647

最后求-1-i  -1的补码为1 111 1111  1111 1111 1111 1111 1111 1111,加上-i补码 1000 0000  0000  0000  0000  0000  0000  0000,
0111 1111  1111 1111 1111 1111 1111 1111,即 2147483647

另外补充一点,计算机中有符号数和无符号数的机器码(补码)是一样的,同一个二进制码按照有无符号输出结果不一样,例如本题中四个答案如果按照无符号整数输出,那么答案就是C

编辑于 2016-02-27 09:47:53 回复(36)
钟表法 简单
发表于 2019-03-11 18:03:47 回复(0)
error C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型
1>已完成生成项目“Project1.vcxproj”的操作 - 失败。
发表于 2017-08-17 11:18:35 回复(0)
个人认为以表盘比较好。以8位为例,有符号 -128~127 无符号 0~255.此处用有符号,然后对照表盘相应前进或后退,此处i初值相当于-128,~i值为127,-i为128即-128,前进1位为-127,后退1位为127(128不存在,就像我们一般都说0点不说24点)

编辑于 2016-09-16 21:45:41 回复(3)
感谢Flyc的指正,我原来的回答确实存在根本性错误,致歉牛友o(╯□╰)o
正数原码、反码、补码形式一致。 负数反码,为其原码的符号位不变,其他位取反; 负数补码,是其反码加1。
举例8bit有符号型整数:
+34原码=反码=补码:00100010
-34原码=10100010,反码=11011101,补码=11011110
==================================
不管是在32还是在64位编译器处理下,int都是4字节32位,所以整数范围是-2147483648~2147483647,数值以补码形式存储。
【注意】最小负数-2147483648=-231 并没有原码和反码,只有补码,由 -0的原码 1 0...0(31个0) 表示
因此:
1、~i:对每一位 取反运算。为01...1(31个1),是正数,补码即原码,即231-1=2147483647;
2、 -i: 对该数求补运算,即【每位】取反运算,再加1。取反, 10...0(31个0)-> 01...1(31个1),再加1得 10...0(31个0), 码表现为 最小负数- 2147483648,并没有原码和反码;
3、1-i:补码形式相加,再推回原码得十进制结果。-i( 10...0(31个0) )+(0 ...1(31个0) )= 10...1(30个0),此为补码形式,补码转 原码为补码减1,再非符号位取反,即原码1...1(32个1)= -(231-1)= - 2147483647
4、 -1-i :补码形式相加,再推回原码得十进制结果。即-i( 10...0(31个0) )+(1 ...1(32个1) )= 01...1(31个1),是正数形式,原码即补码,为231-1= 2147483647
编辑于 2016-02-20 14:05:22 回复(6)
        此题中i = 2^31,32位,为了方便计算,假设为8位,因此 i的补码 = 1 000 0000(符号位和数字位分隔开),这种格式的数,只有补码,没有原码和反码。
~i = ~(1 000 0000) = 0 111 1111(正数,补码即原码)  =  2147483647;
-i  = ~i + 1 = ( 0 111 1111  + 0 000 0001) = 1 000 0000 (即为题中i的补码)=  -2147483648;
-i + 1 = (1 000 0000 + 0 000 0001) = 1 000 0001(补码) = (1~(000 0001 - 1)) = 1 111 1111 (原码)=  -2147483647;
-i - 1 = (1 000 0000 + 1 111 1111(-1的补码)) = 0 111 1111(正数,补码即原码) =  2147483647。

发表于 2016-09-04 20:39:54 回复(0)
Green848的答案里面有些本质性的错误,只不过误打误撞刚好跟实际计算出来的答案一样而已。看来大家对原码、反码、补码、取反运算~、以及单目运算符 - 的理解还不够哈,O(∩_∩)O,相信细心的同学肯定回发现Green848的答案有这样一些问题: 首先,-2147483648这个数为32位int所能表示的最小负整数,而如果原码为 1000 0000  0000  0000  0000  0000  0000  0000(表示-0) ,其反码应为数值位取反,符号位不变,即1111  1111  1111  1111  1111  1111  1111  1111, 补码为反码+1 即为0 000 0000  0000  0000  0000  0000  0000  0000 (最高位溢出,舍去), 而+0 的原码、反码、补码均为 0 000 0000  0000  0000  0000  0000  0000  0000, 如果用 1000 0000  0000  0000  0000  0000  0000  0000作为 -2147483648的原码,则会导致 -2147483648和0的补码表示一样,因此,计算机中规定用 1000 0000  0000  0000  0000  0000  0000 0000来作为 -2147483648的补码,以确保-2147483648~2147483647都有唯一的补码表示; 总结以上内容:正数的原码、反码、补码形式一致,负数的反码为原码的数值位取反,补码为反码+1也即是原码的数值位取反再+1,计算机中以补码表示数据和运算,而32位最小负整数的补码为1000 0000  0000  0000  0000  0000  0000  0000。 然后回到本道题目的解答: 首先,求 ~i , i的补码为1000 0000  0000  0000  0000  0000  0000  0000,取反0111 1111 1111 1111 1111 1111 1111 1111,此为补码,符号位为0,表示正数,正数原码补码一致,因而该数即表示231-1,即2147483647 。 然后,求 -i ,要对一个数值执行单目运算符 -  表示的是对该数取反然后再+1,也即是我们常说的求补运算,注意这里取反+1与原码求补码的区别!也就是求补运算与求补码是不一样的!例子(4位有符号整数):x=-4  1100(补码)   -x=~x+1 也即是 0011+0001=0100(4),而1100再求补码应是先数值位取反,即1011,然后+1,变成1100!注意这两者(求补与求补码)之间的区别。 题目中  i的补码为 1000 0000  0000  0000  0000  0000  0000  0000,取反+1,仍为 1000 0000  0000  0000  0000  0000  0000  0000,即    -2147483648 求 1-i  我们已经求出-i的补码为1000 0000  0000  0000  0000  0000  0000  0000 加上1的补码即为 1000 0000  0000  0000  0000  0000  0000  0001 该补码表示的原码为1 111 1111  1111 1111 1111 1111 1111 1111,即为- 2147483647 最后求-1-i  -1的补码为1 111 1111  1111 1111 1111 1111 1111 1111,加上-i补码 1000 0000  0000  0000  0000  0000  0000  0000, 得 0111 1111  1111 1111 1111 1111 1111 1111,即 2147483647 另外补充一点,计算机中有符号数和无符号数的机器码(补码)是一样的,同一个二进制码按照有无符号输出结果不一样,例如本题中四个答案如果按照无符号整数输出,那么答案就是C
发表于 2017-09-08 17:08:53 回复(0)
我不知道自己理解的有没有问题,这一题我第一次是选错了,选的C,之所以选错原因是因为不知道-2147483648是整数的下限,我理解的补码都是为计算机做加法运算做准备的。
对!补码的出现是对加法运算做准备的,任何数(包括正数负数)之间的运算只需要按照简单的逻辑:异或运算、与运算、移位运算、按位取反等最终实现加法。因而一个数无论正负,它的补码如果按照 按位取反再加1 的法则得出的数必定是其相反数的补码,不信的可以自己去尝试,当然这里说的按位取反是计算机cpu里面的按位取反(所有的位全部取反,谁管你是不是正数负数),这里说的加1运算也仅仅是计算机里面的跟1的补码做加法运算。这就是补码!!!为了运算而生的补码,正数按照补码按位取反再加一得到其相反数,负数也是一样。这样就出现了 0X00000000的相反数等于自身,0X80000000的相反数也等于自身。 0X00000000的相反数之所以是等于自身是因为有了溢出的情况。那么哪一个应该去表示0呢?因为0的相反数为0啊,这两个都满足怎么办?那么这时候出现了一个规定,就是说第一位为1的数为负数。这时候你可能会想为什么第一位1的就要为负数呢??为什么第一位为1的不是正数呢???难道就仅仅是简简单单的规定吗????当然不是咯,你想过没有?如果规定第一位为1的为正数,很多两个正数在计算机的cpu里面做加法运算(一系列的异或运算、与运算、移位运算、按位取反实现)的时候就会得到一个非正数,比如1+1,补码表示是0X80000001+0X80000001,。因为最高为的1做完运算之后得到0,最高位为0就代表了非正,所以说负数的最高位要为1,你这时候会想难道这样就能避免两个负数相加得到一个正说或者两个正数相加得到一个负数??当然不会避免,因为计算机的计算方法是永远不会改变的,但是出现这种情况的时候时候你会知道我计算的数值超出了整数的范围,比如两个整数2000000000+2000000000,当然会得出一个负数啦,不信自己尝试一下,因为你越界了,或者-2000000000-2000000000可能会得到一个正数。至少定义补码第一位为1的时候该数为负数,比定义补码第一位为1的时候该数为正数强。因为定义补码第一位为1的时候该数为正数的时候,来一个int a = 1; int b = 1; int c = a+b;然后得出c是一个负数让人容易接受。
这时候长篇大论扯了这么多,这些就是自己一直理解的补码,看的书里面具体内容都忘了,计算规则也忘了,我就记得了按位取反加一得到相反数的补码是补码的特征,而且计算机都是按照补码进行简单的移位与或非运算的。
~i是多少呢?~i+1 = -i = 2147483648,经过上面的一大段话,这个式子没问题吧,那么很容易得出~i= 2147483647,那-i,1-i,-1-i呢,-i = 2147483648这个正数在整数里面越界了,但是在计算机的cpu里面计算得到的结果2147483648就不要赋值给一个整数了吗?当然要赋值。那么看看-2147483648在计算机里面的表示是1000 0000  0000 0000    0000 0000  0000 0000,按位取反再加1,还是一样的1000 0000  0000 0000    0000 0000  0000 0000,也就是说在计算机里面计算出来的2147483648是张这样的1000 0000  0000 0000    0000 0000  0000 0000,也就是整数里面的-2147483648,1-i那当然就是1+(-2147483648) = -2147483647, -1-i呢就是1000 0000  0000 0000    0000 0000  0000 0000+1111 1111  1111 1111    1111 1111  1111 1111 = 0111 1111  1111 1111    1111 1111  1111 1111,赋值给一个整数也就是2147483647咯。没了,这就是这一题,没有规定0X80000000应该为最小的负数、而0X00000000为0,一切都有因果,没有规定!!!都有因果!!!!因为这样计算机才能计算!!!
编辑于 2017-08-20 23:05:33 回复(0)
基础问题,自己也总搞不明白,其实看4位的情况就足够了。注意其中是规定使用 1000 来作为 -8 的补码,而不是用来表示 -0。
但最后的 -1-i 不知道是怎么算的,是不是编译器在中间提升了类型啊。Flyc 的答案中算的是 -1+i 啊。
编辑于 2017-10-09 17:16:53 回复(0)
这句话很关键:-2147483648表示的是32位的机器的int类型 所能表示的最小负整数没有 没有 没有原码和反码,只有补码,由-0的原码 (1000 0000 0000 0000 0000 0000 0000 0000)表示,其中的1就是符号位。另外还需要注意的是正数的原码、反码、补码形式一致 ,而负数的原码是添加符号位 之后的表现形式,反码是其原码除去符号位之后的数值位全部取反 得到的结果,而 就是 其原码的数值位取反之后再加1(也即反码+1 )。只要明白这个,这个题就so easy了。
发表于 2016-09-03 17:03:13 回复(0)
原码分为+0和-0,补码将-0作为最小负数表示使得表示范围更大。。
发表于 2019-12-27 19:36:43 回复(0)
刚开始举例子的时候,说这个数假如源码是1000 0000 0000 0000 0000 0000 0000 0000的话,取反后加一,最高位就会溢出,是不是有点问题,最高是符号位,它是负数的话,1应该不会变吧,所以和它重了的不应该是+0,而是-0。个人理解,多多指教。
编辑于 2019-08-17 07:59:20 回复(0)
和出栈入栈顺序无关么?
发表于 2019-08-07 20:37:26 回复(0)

1000 0000 0000 0000 0000 0000 0000 0000是32int最小值的补码

发表于 2019-03-03 07:48:31 回复(0)
正数的原码、反码和补码均一致,负数对其原码(除符号位)取反后得到反码,对其原码(除符号位)取反后+1得到补码,计算机用补码进行运算。为保证各数的补码都唯一,i作为最小负数,其补码即为1000 0000 0000 0000 0000 0000 0000 0000,直接取反即可,故选B。
发表于 2018-11-24 16:10:21 回复(0)
补充一下高票答案。
计算机中用补码来表示负数,比如-8,按道理应该是10001000,但是实际上用的是8的补码(取反+1),从00001000变成11110111再变成11111000。计算机中所有的数字都用补码存储,-2147483648只有补码,为1+310
发表于 2018-07-06 12:08:13 回复(0)
原码反码补码
发表于 2018-07-04 12:40:50 回复(0)
(1)表示的数值范围区间是[-2...8, 2...7],是一个环,2...7加1就变成-2...8,-2...8减1变成2...7;
(2)-2...8与2...8是相同的,都表示成-2...8;
发表于 2018-05-10 10:23:47 回复(0)
都是用补码运算 用1000 0000 0000 0000 0000 0000 0000 0000表示i的补码 ~i:对i求反,注意正数的原码和补码一致 -i:求补运算,注意和求补码的区别
编辑于 2018-04-19 08:38:11 回复(0)