Writing Tmin in C (翻译)

CS:APP Web Aside DATA: TMIN :Writing TMin in C

写这篇博客是在看到CSAPP第二章,Tmin写法这一部分。为了给自己加深理解,就将官网上的旁注http://csapp.cs.cmu.edu/public/waside/waside-tmin.pdf翻译了一下。中间有些部分跳过,是因为我觉得于Tmin关系不大,或者是写的太繁复。


谢绝转载

 

1.     案例

在表2-18和练习题2.21中,我们仔细的将Tmin的值写成-2147483647-1。那么为什么我们不将它写成-2147483648或者0x80000000?当我们查看头文件limits.h,发现它和我们使用类似的定义方法来定义Tmin和TMax:

/* Minimum and maximum values a ‘signed int ‘canhold.*/

#define INT_MAX 2147483647

#define INT_MIN (-INT_MAX – 1)

 

不幸的是,补码表示的不对称性和C语言转换规则之间这种奇怪的交互,迫使我们使用奇怪的方式来写Tmin。虽然理解这个问题需要我们专研C语言标准中一些隐晦的角落,但是它也能帮助我们理解整数数据类型和表示的一些细微之处。

 

假设我们将Tmin写成-2147483648,在32位机器中实现,使用表2-8的数据大小。当编译器遇到-X形式的数字时,首先决定X的数据类型和数据值,然后取反。2147483648对于int而言,超出了表示范围。编译器会尝试寻找一个可以准确表示该数值的数据类型。


Figure 1 :表示整形常量的数据类型。依赖C语言版本以及进制(十进制或十六进制),按照顺序第一个可以准确表示数值的数据类型就是所求的。


Figure 2:TMIN的不同数据类型。依赖C语言版本和进制(十进制或十六进制),我们为两种表达式找到了三种不同的数据类型,包括值是正数的案例。

  依照不同的语言版本,它从表一中按照顺序寻找合适的数据类型。对于ISO C90,它从int到long,再到unsigned,直到找到能表示2147483648的数据类型。正如我们在2.3.3看到的那样,在32位机器中,2147483648和-2147483648有相同的位表示,所以最后的数据类型就是unsigned,值是2147483648。而对于ISO C99,最后找到的数据类型是long long,值是-2147483648。

  而对于十六进制常量0x80000000,在32 机器上,最后的数据类型都是unsigned,值是0x80000000(等价于2147483648)。

对于64位及其,无论是ISO C90还是ISO C99,十进制形式的数据类型都是long,值是-2147483648,十六进制都是unsigned,值是0x80000000(等价于2147483648)。

所有的不同都已经在表二中总结,对于结果是longlong long 数据类型的,常量都是负值,并且是64位表示。而对于结果是unsigned的数据类型,常量是正数,并且是32位表示。

这些结果可在下面的代码中明显的看出不同:

Int dcomp = (-2147483648  <  0);

Int hcomp = (0x80000000  <  0);

 

这两行都尝试去表示Tmin,作为十进制或十六进制,并且测试该值是否小于0.依赖于编译器和字的大小,我们可以发现dcomp的值可以是0,也可以是1,这表明十进制常量可能是正数,也可能是负数。但是hcomp的值始终是0,表示十六进制的常量始终是正数。我们看上去很简单的写出Tmin32的任务,比预想的要复杂的多。

 

练习题1:

考虑下面的代码:

Int dtmin = -2147483648;

Int dcomp2 = (dtmin < 0);

Int htmin = 0x80000000;

Int hcomp = (htmin < 0);

 

我们在32位和64位机器上,使用两种不同的补码来表示整形,并且使用ISO-C90和ISO-C99两种方式来编译。在所有的情况中,我们发现dcomp和hcomp2始终都是1,进一步的测试表明,dtmin和htmin事实上等于Tmin(大小)。解释为什么这段代码对不同编译器和语言版本的结果都相同。

 

因为最后都会被转化成int型,那么数值大小就是-2147483648,而不会有歧义。

2 应用

对许多程序而言,由字大小和语言标准引起的模糊不会影响程序的行为(例如问题1)。然而,现在我们可以理解为什么通常的将Tmin 写成-2147483647-1会有一个更合适的结果。因为2147483647就是Tmax的值,因此不需要考虑使用表一的转化规则。

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值