warning: this decimal constant is unsigned only in ISO C90

来源:互联网 发布:淘宝怎么改地址 编辑:程序博客网 时间:2024/06/05 00:58
作者:王赟 Maigo
链接:https://www.zhihu.com/question/22346138/answer/21084638
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

很有趣的问题。
-2147483648并不是一个数值常量,而是一个表达式,它是2147483648这个数值常量前面加了一个单目运算符“-”。
而2147483648本身超出了int型的范围,而你又没有用后缀(L,UL等)指明它的类型,所以会导致undefined behavior。
下面是我想到的,-2147483648这个表达式的几种可能的求值过程:
1) 2147483648超出了int型的范围,溢出后变成了int型的-2147483648。对这个值求相反数,结果2147483648又超出了int型的范围,又溢出变成了int型的-2147483648。结果恰好对了。
2) 2147483648超出了int型的范围,被cast成了unsigned int型的2147483648。对这个值求相反数,结果-2147483648又超出了unsigned int型的范围,又溢出变成了unsigned int型的2147483648。结果差了一个负号。
3) 2147483648超出了int型的范围,被cast成了long int型(64位)的2147483648。对这个值求相反数,结果-2147483648仍在long int型的范围内。结果恰好对了。
上面3种情况都只是“可能”的,具体是哪一种依赖于编译器。作为程序员,不应该依赖这种undefined behavior。

再回到你的程序。
4) int a = -2147483648; 这一句,无论-2147483648经过了上面3种求值过程中的哪一种,最后的结果都会被cast成int型赋给a。这样,a的值一定是-2147483648。所以a/b的计算结果是对的。
5) 而printf("%ld\n", -2147483648/1000000000); 这一句,从你的编译器输出(enabled)来看,应该是把2147483648当成了unsigned int型常量,即采用了上面第2种求值过程。于是结果就反了。

Bonus:
既然-2147483648这个表达式会导致undefined behavior,那么当程序中真的要用到-2147483648这个值的时候,应该怎么办呢?有两种办法:
a) 写成(int)-2147483648。由上面(4)的分析,cast成int型之后值一定是负的。不过,这样做虽然结果正确,但过程中毕竟引发了undefined behavior,并不推荐。
b) 使用INT_MIN。这个宏的定义如下:
#define INT_MIN (-2147483647 - 1)
这个表达式不会引发undefined behavior,且结果确实是-2147483648。


阅读全文
0 0