[译]在C中表示补码最小值

来源:互联网 发布:黑马程序员 课程表 编辑:程序博客网 时间:2024/04/30 20:04

原文链接:[译]在C中表示TMin | Binary Think

在 图CS:APP2e-2.18 和 问题CS:APP2e-2.21,我们将TMin32写作-2147483647-1。为什么不简单的将其写作-2147483648或者0×80000000呢?我们可以看一下C的头文件 limits.h ,我们会发现这个头文件也用了相似的方法来写TMin32TMax32 :

/* Minimum and maximum values a ‘signed int’ can hold. */#define INT_MAX 2147483647#define INT_MIN (-INT_MAX - 1)
不幸的是,C语言中的不对称的补码表示法和C语言转化规则使我们不得不写成这样的形式。虽然要理解这个问题,我们就需要深入C语言标准的一些比较隐晦的角落,但它的确会使我们明白整数类型与其表示的精妙之处。

表一:表示整数常量的数据类型。根据语言版本和格式,常量的数据类型将为列表中找到的第一个合适的类型


表二:TMin32的数据类型结果。根据语言版本和格式,对于两个表达式(Expression)我们能够得到三种不同的数据格式,其中包括值为正的情况。


假设我们把 TMin32 写成-2147483648,并且在32位的机器上面使用图CSAPP2e-2.8的数据大小来编译。当编译器遇到 -X 形式的数字,它会首先决定 X  的类型和值,之后再转化为相反数(注:如果是无符号数,则将该数看作补码形式,取其相反数,但最后结果仍然按无符号数处理),但值2147483648已经超过int型的上界(这个值已经大于TMax32,这就是补码表示法的不对称性)。编译器试图去决定这个值的类型并且分配一个正确的值,于是就去查看表1的表中的十进制栏。如果是ISO C90标准,编译器在遍历int到long,之后再到unsigned,才会发现能够表示 2147483648 的类型。而正如我们在CSAPP2e-2.3.3中看到的,2147483648 和 -2147483648有同样的32位表示(即,补码-2147483648的相反数是其本身,这是由于求相反数的指令是通过汇编级的NEG求补指令的机理决定的),所以结果是unsigned类型(因为不会发生类型转换,原来是unsigned类型,结果仍然为unsigned类型),并且值为2147483648。如果是ISO C99标准,编译器会遍历int到long到long long类型。long long 类型为64位表示(注:这里原文是“With 64 bits”,原译者译为“ 如果是64位的机器”,根据上下文,个人认为此处的意思应为"64位表示",而不是“在64为机上”),2147483648 和 -2147483648 的表示是不同的,所以结果的数据类型是long long,值为-2147483648。

对于32位机器上的十六进制数0×80000000,编译器通过表一的Hexdecimal列来进行类似的遍历。对于两种语言版本来说,编译器首先将这个数与TMax32(0x7FFFFFFF)对比,因为这个数更大一些,所以编译器决定这个数不能被表示为int类型。编译器之后在把它和 UMax32(0xFFFFFFFF)比较,因为这个数更小,所以编译器选择了unsigned类型。

在64位的机器上情况就略有不同。对于两种语言版本,十进制的 -2147483648都被表示为long型并且值为 -2147483648 ,而十六进制被表示为unsigned型并且值为0×8000000(即2147483648)。

所有的这些结果都在表二中总结了出来。对于结果类型是long和long long来说,这个数(指的就是TMin32 )是负值,但却有64位长。对于类型是unsigned来说,这个数是正值并且是32位。这个结果可以被以下代码验证:

int dcomp = (-2147483648 < 0);int hcomp = (0x80000000 < 0);
这两行代码分别把按照十进制或者十六进制数来表示并且判断是否小于0。通过不同的编译器版本和标准调试后,我们会看到dcomp的结果0和1都会出现,说明结果有可能是正的也可能是负的,而hcomp的值却一直是0,说明十六进制下的值一直是负的。看似简单的表示似乎比我们预期的要难一些。

对于很多程序,由于不同字长和语言标准而引起的差异不会影响程序的行为。尽管如此,我们还是知道了为什么把TMin32表示为-2147483647-1会产生一个更可靠的结果。因为2147483647是TMax32的值,所以能够被表示为int类型,这样就不会再触发表一的转换规则。

原文还有三道小例题,感兴趣的可以看看。

原文PDF下载:http://www.csapp.cs.cmu.edu/public/waside/waside-tmin.pdf

0 0