关于 C++ 里面的 INT_MIN

2014-08-25 22:47:19 +08:00
 winterma
if (-2147483648 > 0) printf("positive\n");
if (-2147483647 - 1 < 0) printf("negative\n");

结果是两次if都为真。
不明白的是第二次为什么会判断为真?-2147483647 - 1计算机是如何进行处理的?
5086 次点击
所在节点    问与答
11 条回复
skydiver
2014-08-25 22:50:11 +08:00
反汇编一下看看
nopy
2014-08-25 22:50:59 +08:00
YouXia
2014-08-26 02:09:05 +08:00
内存里面补码表示,负数除符号位外,取反加1,而减1,其实是加负1(也是补码表示)。
zwzmzd
2014-08-26 09:39:47 +08:00
http://blog.csdn.net/seizef/article/details/7605010
和编译器语法分析的设计有关
glogo
2014-08-26 09:42:01 +08:00
LZ 可以看看《深入理解计算机操作系统》讲信息在计算机中表示的那一节,有讲到这个问题的~
stackpop
2014-08-26 09:51:17 +08:00
4楼是正解.
用clang编译, 楼主的两个if都是false
第二个if, 有些编译器可能会认为和 if( -2147483647 < -1 )是等价的, 有些编译器可能会先做减法再做大小比较.亦或者和<所代表的位运算有关.
Monad
2014-08-26 09:56:59 +08:00
我想知道楼主用的啥编译器试出来的
winterma
2014-08-26 14:43:59 +08:00
@Monad 就是GCC啊
winterma
2014-08-26 14:46:16 +08:00
@stackpop -2147483647 - 1算出来的结果应该是100.....00(31个0), 也就是负零,不知道负零在计算机里面有什么含义吗?
zwzmzd
2014-08-26 19:14:49 +08:00
@winterma 补码表示中零只有一种表示,那就是0x00000000(32位情况下),没有什么正零负零的区别。

LZ可以用下面代码显示INT_MIN的十六进制表示:
printf("0x%08x\n", INT_MIN);

还有就是要注意的是,补码可表示的数字范围,负数会比正数多一个(正是因为零的存在)

0x00000000 对应 0
0x00000001~0x7fffffff 对应正数 1~2147483647
0x80000000~0xffffffff 对应负数 -2147483648~-1(注意对应顺序,是反着的)

按照上面的表将这些数字画到一个环上去,这个数环蕴含了正无穷和负无穷相接的思想


你直接写-2147483648,gcc将其认为是一个表达式,即一个负号(-)和一个立即数(2147483648),而2147483648不是32位计算机中可以直接表示的数字(数环里没有这个数字),所以gcc在编译的时候会有warning出现,并且对于这个情况会采用一些默认处理,造成了意料之外的结果。
winterma
2014-08-27 15:00:01 +08:00
@zwzmzd 非常感谢你的解答,完全明白了! 我之前一直认为int可表示的正负数一样多,所以觉得0x80000000是多出来的东东... 再次感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/129868

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX