This commit is contained in:
许大仙 2024-08-22 17:23:35 +08:00
parent d57207c1ae
commit 8cbdfd4d1a
3 changed files with 67 additions and 0 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 443 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 156 KiB

View File

@ -1321,3 +1321,62 @@ int main() {
> >
> `补码`这种天才般的设计,一举达成了之前加法运算和减法运算提到的两个目标,简化了硬件电路。 > `补码`这种天才般的设计,一举达成了之前加法运算和减法运算提到的两个目标,简化了硬件电路。
## 3.8 问题引入
* 在 C 语言中,对于`有符号位`的整数,是使用 `0` 作为正数,`1` 作为负数,来表示`符号位`,并使用`数据位`来表示的是数据的`真值`,如下所示:
```c
int a = 10;
int b = -10;
```
![](./assets/43.svg)
* 但是,对于`无符号位`的整数而言,是`没有`符号位和数据位,即:没有原码、反码、补码的概念。无符号位的整数的数值都是直接使用二进制来表示的(也可以理解为对于无符号位的整数而言,计算机底层存储的就是其原码),如下所示:
```c
unsigned int a = 10;
unsigned int b = -10;
```
![](./assets/44.svg)
* 这就是导致了一个结果就是:如果我定义一个`有符号`的负数,却让其输出`无符号`,必然造成结果不对,如下所示:
```c
#include <stdio.h>
char *getBinary(int num) {
static char binaryString[33];
int i, j;
for (i = sizeof(num) * 8 - 1, j = 0; i >= 0; i--, j++) {
const int bit = (num >> i) & 1;
binaryString[j] = bit + '0';
}
binaryString[j] = '\0';
return binaryString;
}
int main() {
// 禁用 stdout 缓冲区
setbuf(stdout, NULL);
int num = -10;
printf("b=%s\n", getBinary(num)); // b=11111111111111111111111111110110
printf("b=%d\n", num); // b=-10
printf("b=%u\n", num); // b=4294967286
return 0;
}
```
* 其实C 语言的底层逻辑很简单C 语言压根不关心你定义的是有符号数还是无符号数,它只关心内存(如果定义的是有符号数,那就按照有符号数的规则来存储;如果定义的是无符号数,那就按照无符号数的规则来存储)。换言之,有符号数可以按照无符号数来输出,无符号数也可以按照有符号数来输出,至于输出结果对不对,那是程序员的事情,和 C 语言没有任何关系。
> [!IMPORTANT]
>
> * ① 正因为上述的原因很多现代化的编程语言Java 等,直接取消了无符号的概念。
> * ② 对于 `1000 0000 …… 0000 0000` 是个特殊的补码,无法按照上述的方法转换为原码,所以计算机直接规定这个补码对应的值就是 `-2³¹`,至于为什么,下节我们会详细分析。