您的位置:首页 > 编程语言 > C语言/C++

c语言里面TMin不能写成-2147483648的原因

2016-07-15 19:15 169 查看
C语言中,将TMin(32位有符号整数的最小值)写成 -2147483647-1,而不是简单地写成 -2147483648 或 0x80000000 。这是为什么呢?

首先,对于整数常量的定义:

An integer constant begins with a digit, but has no period or exponent part. It may have a prefix that specifies its base and a suffix that specifies its type.


可见如果不发生溢出,整型常量的值总是非负数。如果前面出现符号,则是对整型常量使用的一元运算符,而不是整型常量的一部分。整型常量的实际类型取决于长度、基数、后缀字母和C语言实现确定的类型表示精度。具体的根据表一来确定。

  

其次,看看C语言中limits.h中对于INT_MIN和INT_MAX的定义如下所示:

#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)


那么考虑到以上两点,如果将TMin32写成-2147483648并且将代码在一个32位的机器上面编译,当编译器遇到-X形式的数值,它首先会确定X的数据类型和值,然后取X的。

ISO C90ISO C99
十进制(Decimal)十六进制(Hexadecimal)十进制(Decimal)十六进制(Hexadecimal)
int
long
unsigned
unsigned long
int
unsigned
long
unsigned long
int
long
long long

int
unsigned
long
unsigned long
long long
unsigned long long
表一 根据C语言版本和常量的格式(十进制和十六进制),常量的数据类型是从上面表格里选择第一个合适(能表示常量)的类型。

Wor
4000
d Size
ISO C90ISO C99
Expression-21474836480x80000000-21474836480x80000000
32
64
unsigned
long
unsigned
unsigned
long long
long
unsigned
unsigned
表二 根据C语言版本和常量的格式(十进制和十六进制),可以为这两个表达式得到三种不同的数据类型,包括数据为正值的情况。

由于2147483648超过了int所能够表示的范围,编译器就会再次选择一种可以正确的表示此值的类型。然后它就会按照第一个表格(十进制)的顺序往下继续尝试类型,再假设编译器采用的标准是ISO C90,int->long->unsigned,然后就发现unsigned是第一个合适的数据类型。正如我们知道的,2147483648和-2147483648在32位数值上拥有同样的位表示,使得此常量的最终数据类型是unsigned且值为2147483648。这对于16进制的0x80000000也是相同的结果。

对于64位来说十进制和十六进制会分别选择long(-2147483648)和unsigned(2147483648)。而ISO C99的情况则是按照上述规则数据类型为long long才能容纳2147483648。

最后结论是:-214748364832位机器里使用ISO C90进行编译,会先将2147483648看成是一个unsigned,再对2147483648进行无符号的加法逆元计算(见csapp第二版56页),得到结果是:

(-uw2147483648) = 2w - x = 232 - 231 = 231 = 2147483648。

所以对于下面的表达式:

int result = -2147483648 < 2147483647;


在32位机器里面使用ISO C90进行编译, result = 0。

参考资料:

cs: app web aside
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: