Skip to content

Commit

Permalink
Update: Improve description of left shift and right shift operations
Browse files Browse the repository at this point in the history
  • Loading branch information
dynilath committed Jul 25, 2024
1 parent 67db20e commit 16cdcf9
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions src/zh/02-program-structure/expression.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,22 +299,30 @@ true + 2 // 值为 3
```cpp
42 << 2 // 值为 168
```
假设 `int` 是32位的,`42` 的二进制表示是 `0000 0000 0000 0000 0000 0000 0010 1010`,左移两位后的二进制表示是 `0000 0000 0000 0000 0000 0001 0100 0000`,转换为十进制就是 `168`
当结果不超过范围时,读者可以简单地认为左移`N`位就是乘以 `2^N`。相对的,右移`N`位就是除以 `2^N`(整数除法)。
假设 `int` 是32位的,`42` 的二进制表示是 `0000 0000 0000 0000 0000 0000 0010 1010`,左移两位后的二进制表示是 `0000 0000 0000 0000 0000 0000 1010 1000` (用 `0` 补充移出来的位),转换为十进制就是 `168`

当结果不超过范围时,读者可以简单地认为左移 `N` 位就是乘以 `2^N`。相对的,右移 `N` 位就是除以 `2^N`(向下取整)。

如果左移的结果超过范围,例如:
```cpp
42 << 30
```
`42`的二进制表示是 `0000 0000 0000 0000 0000 0000 0010 1010`左移31位后的二进制表示是 `1000 0000 0000 0000 0000 0000 0000 0000` (超出范围的位会被舍弃),最后这个结果转换为十进制就是 `-2147483648`
`42`的二进制表示是 `0000 0000 0000 0000 0000 0000 0010 1010`左移30位后的二进制表示是 `1000 0000 0000 0000 0000 0000 0000 0000` (超出范围的位会被舍弃),最后这个结果转换为十进制就是 `-2147483648`

任何情况下,如果移位表达式的右边的值是负数,或者超过了左边值的位数,那么这个表达式的行为是未定义的。
任何情况下,如果移位表达式的右操作数是负数,或者超过了左边值的位数,那么这个表达式的行为是未定义的。

类似于加性表达式,移位表达式会进行[整数提升](#整数提升)。例如:
```cpp
true << 2 // 值为 4
'a' << 2 // 值为 388
```

对于 `int` 类型的负值,右移操作在左边补充的是 `1`,而不是 `0`。例如:
```cpp
-42 >> 2 // 值为 -11
```
`-42` 的二进制表示是 `1111 1111 1111 1111 1111 1111 1101 0110`,右移两位后的二进制表示是 `1111 1111 1111 1111 1111 1111 1111 0101`,转换为十进制就是 `-11`。显然,即使是负数,右移操作也是向下取整的除以 `2^N`。需要注意,这里的除法是向下取整的,而非向零取整,即 `-42 / (2 ^ 2) = -11 ... 3`。于是,容易观察到,如果右移时,右操作数的值是左边的位数,正数会变成 `0`,而负数会变成 `-1`

::: tip 移位强迫症
设计移位是因为在计算机中,移位操作是非常高效的。在一些情况下,移位操作可以取代乘法和除法,从而提高程序的性能。

Expand Down

0 comments on commit 16cdcf9

Please sign in to comment.