Why is 0 < -0x80000000?

在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 类型,直到它可以完成正确的存放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值