补一下CSAPP的笔记

计算机中整数的表示与编码

计算机中的整数主要包括两种:有符号数与无符号数。

无符号数的编码

其中有符号数的表示方法与传统二进制一致。
假设有一个整数数据类型有w位。我们可以将位向量写成
TIM截图20191119165609.png
在这个编码中,每个xi都取值为0或1。我们用一个函数来表示B2Uw来表示:
TIM截图20191119165522.png
无符号数的编码方式实际上与我们所知道的二进制编码方式是一致的。唯一要注意的是无符号数的编码具有唯一性,也就是说一个数字只能有一个无符号数编码。这是因为B2Uw是一个双射。

有符号数的编码

有符号数的编码主要有三种方式:原码、补码与反码。我曾经写过一篇博客来进行探究,这里不赘述。

如果有符号数的真值小于0那么,把真值加上2w即为其无符号真值,如果真值大于0,那么不变。
我们用一段C语言代码举例:

#include<stdio.h> #include<stdlib.h> #include<limits.h> int main(void) {     int i = -1;     unsigned int j = (unsigned int)i;     printf("%u\n", j);     printf("%u\n", UINT_MAX);     system("pause"); }

VS2017下的运行结果:
TIM截图20191117170002.png
数据类型int的大小为8字节,32位,把-1转换成无符号数需要加上232,结果为232-1,正好为无符号数编码的最大值,所以与UINT_MAX的值一致。

无符号数转有符号数

直接给出公式:
TIM截图20191119165535.png
C语言代码测试实例:

#include<stdio.h> #include<stdlib.h> #include<limits.h> int main(void) {     unsigned int i = UINT_MAX;     int j=(int)i;     printf("%d", j);     system("pause"); }

VS2017下的运行结果:
TIM截图20191117172003.png

需要说明的是,在VS2017的环境下,上面两个程序经过测试即使不使用强制类型转换也可以得到正确的结果,其一是C语言中如果发现左右两边数据类型不一致会自动把数据往左边的类型转换,其二是,printf中的格式说明符也会自动执行类型转换,这里使用强制类型转换只是为了让转换看起来更加清晰。

无符号整数与有符号整数互相转换可能遇到的问题

由于C语言对同时包含有符号和无符号数表达式的这种处理方式,出现了一些奇特的行为。当执行一个运算时如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式地把有符号参数强制类型转换为无符号,并假设这两个数都是非负的
对于<和>这样的关系运算符来说,它会导致非直观的结果。我们同样用一个C语言程序来作为测试:

#include<stdio.h> #include<stdlib.h> int main(void) {     printf("%d", -1 < 0U);     printf("%d",(unsigned)-1 > -2); }

VS2017运行结果:
TIM截图20191117180823.png
第一个表达式中,由于0是无符号数,所以-1默认变成无符号数,即为232-1,这个数必然比0要大。所以第一个表达式为假。
第二个表达式中,通过把-1强制转换成无符号数,-1变为232-1,-2变为232-2,所以第二个表达式为真。