这个小结我们要探讨一个相对来说简单的问题,就是 c 语言里边的那些定点整数是如何进行强制类型转换的。
一、案例一
来看这样的一个例子。
首先需要跟大家声明的是, c 语言当中的定点整数,大家熟悉的什么 Int 还有什么 short 还有long,这些定点整数都是用补码
的形式来存储的。
另外, c 语言里还有一个关键字叫unsigned,如果用 unsigned 来修饰 short 或者 Int 或者long,那就意味着这个定点整数它是一个无符号数。
现在有一个 short 型的短整数x,它的值是-4321。如下:
由于是采用补码表示的,并且短整形是占两个字节,也就是 16 个比特,所以 16 个比特的补码表示- 4321 应该是这样的一个值(如下)。这些大家可以自己转换一下。
原码补码如何转换,我们之前已经强调过,不熟悉的同学可以再自己动手试一下。
现在我们把 x 这个短整形的数强制转换成 unsigned short,也就是无符号的短整形y。这种强制转换的规则是,会把 x 的补码形式的数完整不变的复制给 y 变量。
由于 y 也是占两个字节,所以 y 的机器代码其实和 x 是一模一样的。只不过由于 y 是一个无符号的短整形,因此计算机在解析 y 的真值的时候,会按照无符号整数来进行解析。所以把二进制无符号数转换成真值应该是对应值61215。如下:
这是一个有符号的定点整数,转换成长度相同的无符号定点整数的规则。不改变数据的二进制内容,但是会改变它的解释方式。
二、案例二
再看第二个例子。
如果我们把一个更长的数据,变成一个更短的数据,比如我们定义了两个 Int 型的变量 a 和b。
大多数情况下, c 语言里边 Int 型的数据占 4 个字节。
现在 a 和 b 是两个有符号的数,都用补码的形式来保存。当我们把 a 和 b 这两个数强制转换成short,也就是由 4 个字节变成 2 个字节的时候,计算机的做法是,直接把高位截断,只保留低位。
①a对应的 16 进制应该是这样的(如下),把后四个字节的内容截断,只保留最低两个字节的内容,也就是 86A1。
更低的两个字节就是 c 变量的值。由于 c 是一个有符号的短整形,所以计算机会用补码的规则来对它进行解析。与之对应的真值应该是-31071这样的值,这是一个 16 比特 16 位的补码。
②对于 b 和 d 也是一样的, b这个数它用补码表示如下:
把 b 转换成只有两个字节的 d short 类型,只保留更低的两个字节7751。
同样的,由于 d 它是一个有符号的短整形,所以计算机会用 16 比特补码的方式来对它进行解析,与之对应的真值如下:
这是更长的数据转换成更短的数据的处理方式。很残暴,直接截断,只保留更低的字节。
三、案例三
最后再来看更短的数据转换成更长的数据。这个问题其实我们之前聊过,也就是所谓符号扩展的问题。
x 原本是一个两个字节的补码,总共占 16 位。
把 short 型的 x 转换成 4 字节的 Int 型。计算机做的事情就是符号扩展。
①先来看m变量
之前我们说过,对于一个定点整数的补码来说,如果它是一个负数
,我们需要在高位,也就是符号位和原有的数值位之间添1,用这样的方式扩展得到的补码,你把它解析为真值,这个真值是不会变的,只不过是补码的整体长度拓展了而已。
②再来看n 变量
我们把 x 强制的转换为无符号类型,把它赋值给无符号的短整形n。
之前我们说过,这种强制转换会把二进制代码原封不动的复制给n,只不过计算机会以无符号数的规则来解析这一串机器数,这是 n 所对应的一个真值(如下)。
③变量p
最后把无符号数 n 变成 4 个字节的无符号数p。
由于是无符号数到无符号数的转变,因此直接在高位填 0 就可以了。
p 和 n 的真值,这个真值是保持不变的。如下:
四、总结
这就是 c 语言里边定点整数相关的一些强制类型转换。
第一个部分探讨的是在转换的两种数据长度相同的情况下,无符号数和有符号数之间的一种转换规则。
第二个部分探讨的是从长数据强转成短数据的一个处理方式。
第三个部分探讨的是从短数据转为长数据的一个转变方式。