您的位置:首页 > 编程语言 > C语言/C++

读书笔记:C++ Primer系列(2)—— 整型赋值问题

2013-12-17 19:44 148 查看
知识储备:

1. 有符号数与无符号数

有符号数和无符号数是针对二进制来讲的。

有符号数用最高位作为符号位,“0”代表“+”,“1”代表“-”;其余数位用作数值位,代表数值。
无符号数全部二进制均代表数值,没有符号位。即第一个"0"或"1"不表示正负。

例如:

无符号数: 1111 1111 值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20
有符号数: 0111 1111 值:127 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。无符号的最小值是 0 ,而有符号数的最小值是-128。即:

无符号数: 0 ----------------------- 255
有符号数: -127 --------- 0 ------------ 127 也可记成 -128 --------- 0 ------------ 127

2. 机器数、真值、原码、反码、补码

机器数

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机中用一个数的最高位存放符号, 正数为0, 负数为1。

比如:以单字节(8位)为例,十进制数+5,转换成二进制为:0000 0101,十进制数-5,转换为二进制为:1000 0101;其中的0000 0101和1000 0101就是+5和-5在计算机中的机器数。

真值

将带符号位的机器数的真正数值称为这个数的真值。

比如:带符号数:0000 0011的真值=+000 0011=+3; 1000 1001的真值=-000 1001=-7

原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。(我的理解:原码就是某个数的机器数或者是二进制形式)。以单字节为例:

[+1]原=0000 0001 [-1]原=1000 0001

因为第一位是符号位,所以单字节数的取值范围是[1111 1111 0111 1111]即[-127 +127]

反码

反码的表示规则:

正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。

[+1]反=0000 0001 [-1]反=1111 1110

补码

补码的表示规则:

正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1(即在反码的基础上+1)。

[+1]补=0000 0001 [-1]补=1111 1111

从上面可以看到,原码、反码、补码是完全不同的,而我们计算机中存放数值是存放的补码,这是为什么呢?为什么计算机不直接采用原码或反码呢?

这是因为考虑到减法问题,且看下面分析

[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补

[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补

计算十进制数1与1相减:1-1=0

如果计算机采用原码,就会出现:1-1=1+(-1)=[0000 0001]原+ [1000 0001]原=[1000 0010]原=-2,结果显然不对。

如果计算机采用反码,就会出现:1-1=1+(-1)=[0000 0001]反+[1111 1110]反=[1111 1111]反=[1000 0000]原=-0,显然也不是我们想要的结果,因为在0前面加上”+“或”-“没有意义。

如果计算机采用补码,则1-1=1+(-1)= [0000 0001]补+ [1111 1111]补=[0000 0000]补=[0000 0000]原=0,符合预期结果

这里有一个问题:当用补码计算(-1)-(127)时,应该是-128

-1-127=(-1)+(-127)=[1111 1111]补+[1000 0001]补=[1000 0000]补

注:在用补码运算的结果中, [1000 0000]补 就是-128。 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示。

对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原,这是不正确的。

$关于整型的赋值问题

C++ Primer(第四版)P32提到:对象的类型决定对象的取值。疑问:当把一个超出其取值范围的值赋给一个指定类型的对象时,结果如何?-——答案为取决于这种类型的是signed还是unsigned的。

比如对于8位的unsigned char类型,其取值范围为0到255(包含255),如果赋给超出这个范围的值,那么编译器会取该值对256求模后的值。如:将336赋给一个8位的unsigned char中,则实际赋值为80(因为80是336对256求模后的值)

而对于unsigned类型来说,负数总是超出其取值范围的。但C++中,将负数赋值给一个unsigned对象是完全合法的,其结果是该负数对该类型的取值个数求模后的值。

如:将-1赋给8位的unsigned char,则结果是255(-1 mod 256=255)

这里涉及到负数进行mod运算,公式如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: