提交 a7f31a47 编写于 作者: W wizardforcel

ch5.

上级 b47b8d0e
# 第五章 更多的位与字节
> 作者:[Allen B. Downey](http://greenteapress.com/wp/)
> 原文:[Chapter 5 More bits and bytes](http://greenteapress.com/thinkos/html/thinkos006.html)
> 译者:[飞龙](https://github.com/)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
## 5.1 整数的表示
你可能知道计算机以二进制表示整数。对于正数,二进制的表示法非常直接。例如,十进制的5表示成二进制是`0b101`
对于负数,对清晰的表示法使用符号位来表明一个数是正数还是负数。但是还有另一种表示法,叫做“补码”(two's complement),它更加普遍,因为它和硬件配合得更好。
为了寻找一个正数的补码,`-x`,需要找到`x`的二进制表示,将所有位反转,之后加上1。例如,要表示十进制的`-5`,要先从十进制的5开始,如果将其写成8位的形式它是`0b0000 0101`。将所有位反转并加以会得到`0b1111 1011`
在补码中,最左边的位相当于符号位。正数中它是0,负数中它是1。
为了将8位的数值转换为16位,我们需要对正数添加更多的0,对负数添加更多的1。实际上,我们需要将符号位复制到新的位上,这个过程叫做“符号扩展”。
在C语言中,除非你用`unsigned`声明它们,所有整数类型都是有符号的(能够表示正数和负数)。它们之间的差异,以及这个声明如此重要的原因,是无符号整数上的操作不使用符号扩展。
## 5.2 按位运算
学习C语言的人有时会对按位运算`&``|`感到困惑。这些运算符将整数看做位的向量,并且在相应的位上执行逻辑运算。
例如,`&`执行“且”运算。如果两个操作数都为1结果为1,否则为0。下面是一个在两个4位数值上执行`&`运算的例子:
```
1100
& 1010
----
1000
```
C语言中,这意味着表达式`12 & 10`值为8。
与之相似,`|`执行“或”运算,如果两个操作数至少一个为1结果为1,否则为0。
```
1100
| 1010
----
1110
```
所以表达式`12 | 10`值为14。
最后,`^`运算符执行“异或”运算,如果两个操作数其中有一个为1,而不是全部为1,结果为1。
```
1100
^ 1010
----
0110
```
所以表达式`12 ^ 10`值为6。
通常,`&`用于清除位向量中的一些位,`|`用于设置位,`^`用于反转位。下面是一些细节:
**清除位:**对于任何`x``x & 0`值为0,`x & 1`值为`x`。所以如果你讲一个向量和3做且运算,它只会保留最右边的两位,其余位都置为0。
```
xxxx
& 0011
----
00xx
```
在这个语境中,3叫做“掩码”,因为它选择了一些位,并屏蔽了其余的位。
**设置位:**与之相似,对于任何`x``x | 0`值为`x``x | 1`值为1。所以如果你将一个向量与3做或运算,它会设置右边两位,其余位不变。
```
xxxx
| 0011
----
xx11
```
**反转位:**最后,如果你将一个向量与3做异或运算,它会反转右边两位,其余位不变。作为一个练习,看看你能否使用`^`计算出12的补码。提示:-1的补码表示是什么?
C语言同时提供了移位运算符,`<<``>>`,它可以将位向左或向右移。向左每移动移位会使数值加倍,所以`5 << 1`为10,`5 << 2`为20。向右每移动移位会使数值减半(向下取整),所以`5 >> 1`为2,`2 >> 1`为1。
## 5.3
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册