您的位置:首页 > 其它

Why is 0 < -0x80000000?

2016-08-27 21:28 155 查看
在Leetcode的Pow(x, n)中,有一组特殊的测试数据,即
1.0 -2147483648
(求1.0^-2147483648)。同时我也发现Stack Overflow上一个与之类似的问题和答案。提问和回复都很精彩,就着手翻译一下(其实是为了加深记忆)。

问题地址:Why is 0 < -0x80000000?



#include <stdio.h>
#define INT32_MIN        (-0x80000000)
int main(void)
{
long long bal = 0;
if(bal < INT32_MIN )
{
printf("Failed!!!");
}
else
{
printf("Success!!!");
}
return 0;
}


条件
if(bal < INT32_MIN)
总是真,与我的预期不符。

当我进行了修改
#define INT32_MIN (-2147483648L)
后,程序正常工作。



这很难察觉。

每一个整数字面值在你的程序中都有一个类型。这些类型有如下标准,如表6.4.4.1:

Suffix      Decimal Constant    Octal or Hexadecimal Constant
none        int                 int
long int            unsigned int
long long int       long int
unsigned long int
long long int
unsigned long long int


如果一个数的字面值不能存放在默认的
int
类型中,它将试图采用下一个类型(如表6.4.4.1)所示。所以对于十进制整数字面值,将进行如下过程:

尝试
int


如果不能存放,尝试
long


如果还不能存放,尝试
long long


而十六进制的字面值的行为与上述过程大不相同。如果字面值不能存放在一个有符号类型如
int
中,在它提升类型前会首先将尝试存放在
unsigned int
。我们可以从表6.4.4.1中看出其中的差异。

所以在一个32位操作系统中,你的字面值是
0x80000000
是一个
unsigned int
类型。

这意味着你对它使用一元操作符
-
将不能达到相应的效果( 一元负运算符应用于无符号类型,结果仍为无符号类型)。另一种情况是它会造成一个有符号整数的溢出。相反的,你将得到值
0x80000000
,一个正值。

bal < INT32_MIN
将执行常见的算数类型转换,表达式中的
0x80000000
将从
unsigned int
转换为
long long
类型存放,0小于
0x80000000
,因此产生了如此结果。

当你使用十进制形式将字面值替换为
2147483648L
后,编译器将不再选择
unsigned int
, 而是尝试将它存放在一个
long
类型中。还有后缀
L
意味着如果可能的话,你想用一个
long
类型来进行存放。后缀
L
通常遵守相同的规则(如表6.4.4.1):如果这个数不能存放在它所请求的
long
类型中,编译器将会给你一个
long long
类型,直到它可以完成正确的存放。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息