小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(二)

小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(二)

欢迎来到小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(二)。本文将延续上篇内容,继续为大家抒写:2.2整数表示

我们都知道C语言是最古老的语言,它支持两种整数表示,一种是只可以表示非负数的无符号数,另一种是正负数都可以表示的有符号数。虽然在更加古老的年代中,负数表示除了补码以外,还有反码和原码来表示负数;但因为现代计算机都默认以补码来实现,所以作者直接把补码等同于有符号数。

尴尬的是,在2.2开篇,作者就直接扔你一脸函数表格,让读者不知所措。小护士表示见过大场面,直接忽略掉。

2.2.1 整型数据类型

这小节介绍了C语言数据类型的取值范围。其中特别表明,long类型在32位系统和64位系统有不同的数据长度表现,因此,C语言设计了int32_tint64_t来明确这种取值范围。

由于,当前大部分系统都可以运行64位程序,小护士为了方便大家复习,就在这里列出数值表格:

C数据类型 最小值 最大值
[signed] char -128 127
unsigned char 0 255
short -32 768 32 767
unsigned short 0 65 535
int -2 147 483 648 2 147 483 647
unsigned 0 4 294 967 295
long -9 223 372 036 854 775 808 9 223 372 036 854 775 807
unsigned long 0 18 446 744 073 709 551 615
int32_t -2 147 483 648 2 147 483 647
uint32_t 0 4 294 967 295
int64_t -9 223 372 036 854 775 808 9 223 372 036 854 775 807
uint64_t 0 18 446 744 073 709 551 615

Java没有无符号数。:)

2.2.2 无符号数的编码

什么都不用说,故意无视数学细节,直接上二进制转十进制等式:

[0001]=023+022+021+120=0+0+0+1=1 [ 0001 ] = 0 ∗ 2 3 + 0 ∗ 2 2 + 0 ∗ 2 1 + 1 ∗ 2 0 = 0 + 0 + 0 + 1 = 1

[0101]=023+122+021+120=0+4+0+1=5 [ 0101 ] = 0 ∗ 2 3 + 1 ∗ 2 2 + 0 ∗ 2 1 + 1 ∗ 2 0 = 0 + 4 + 0 + 1 = 5

[1011]=123+022+121+120=8+0+2+1=11 [ 1011 ] = 1 ∗ 2 3 + 0 ∗ 2 2 + 1 ∗ 2 1 + 1 ∗ 2 0 = 8 + 0 + 2 + 1 = 11

[1111]=123+122+121+120=8+4+2+1=15 [ 1111 ] = 1 ∗ 2 3 + 1 ∗ 2 2 + 1 ∗ 2 1 + 1 ∗ 2 0 = 8 + 4 + 2 + 1 = 15

2.2.3 补码编码

什么都不用说,继续无视数学细节,还是那道二进制转十进制等式:

[0001]=023+022+021+120=0+0+0+1=1 [ 0001 ] = − 0 ∗ 2 3 + 0 ∗ 2 2 + 0 ∗ 2 1 + 1 ∗ 2 0 = 0 + 0 + 0 + 1 = 1

[0101]=023+122+021+120=0+4+0+1=5 [ 0101 ] = − 0 ∗ 2 3 + 1 ∗ 2 2 + 0 ∗ 2 1 + 1 ∗ 2 0 = 0 + 4 + 0 + 1 = 5

[1011]=123+022+121+120=8+0+2+1=5 [ 1011 ] = − 1 ∗ 2 3 + 0 ∗ 2 2 + 1 ∗ 2 1 + 1 ∗ 2 0 = − 8 + 0 + 2 + 1 = − 5

[1111]=123+122+121+120=8+4+2+1=1 [ 1111 ] = − 1 ∗ 2 3 + 1 ∗ 2 2 + 1 ∗ 2 1 + 1 ∗ 2 0 = − 8 + 4 + 2 + 1 = − 1

补码就是把第一位(高位)作为符号表示,1为负数,0为正数。

补码的正数与负数不对称,是因为用了最高位的1作为负数标记符号。

其他补充:
[1111 [ 1111 1111]= 1111 ] = 0xFF =1 = − 1
[0000 [ 0000 0000]= 0000 ] = 0x00 =0 = 0

补码最小值:
8位字长: 0x80 =128 = − 128
16位字长:0x8000 =32768 = − 32768

补码最大值:
8位字长: 0x7F =127 = 127
16位字长:0x7FFF =32767 = 32767

2.2.4 ~ 2.2.5 有符号数与无符号数的转换

怎么转?位不变,直接用不同的二进制转十进制等式就行了。
因为二进制的数位不变,所以实际上就是没转。

2.2.6 ~ 2.2.7 整型数据类型强转处理:扩展与截断

关于扩展的画风是这样的:

类型 十进制 十六进制
short -12345 0x CF C7
unsigned short 53191 0x CF C7
int -12345 0x FF FF CF C7
unsigned int 53191 0x 00 00 CF C7

大家肯定会觉得如下有符号数等式很奇怪:

int
0xCFC7 == 0xFFFFCFC7

手算一下就知道了,不解释,小学数学范畴。


关于截断的画风是这样的:

类型 十进制 十六进制
int 53191 0x 00 00 CF C7
unsigned int 53191 0x 00 00 CF C7
short -12345 0x CF C7
unsigned short 53191 0x CF C7

所谓的截断就是把高位的位数砍掉,例如8位数截断到4位数,则把前4位(高位的4位)砍掉。

由于补码以最高位作为符号标记,所以出现截断时,才会有可能得出负数的结果。

2.2.8 关于有符号数与无符号数的建议

小护士一句话概括:
不要随便转来转去。

小护士再来一句:
要是在C语言代码中出现这种无符号与有符号互转的,代码评审直接不通过。:)

小结

2.2就是讲讲无符号与有符号(补码)的恩怨情仇。下一篇,《深入理解计算机系统》第二章信息的表示和处理(三),2.3整数运算,将会给大家讲述无符号数与有符号数的加减乘除法。别走太远哦。

你可能感兴趣的:(深入理解计算机系统,读书笔记)