From 8cbdfd4d1a644d1550771be2a378ff15c36c2fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E5=A4=A7=E4=BB=99?= <1900919313@qq.com> Date: Thu, 22 Aug 2024 17:23:35 +0800 Subject: [PATCH] c --- docs/notes/01_c-basic/02_xdx/assets/43.svg | 4 ++ docs/notes/01_c-basic/02_xdx/assets/44.svg | 4 ++ docs/notes/01_c-basic/02_xdx/index.md | 59 ++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 docs/notes/01_c-basic/02_xdx/assets/43.svg create mode 100644 docs/notes/01_c-basic/02_xdx/assets/44.svg diff --git a/docs/notes/01_c-basic/02_xdx/assets/43.svg b/docs/notes/01_c-basic/02_xdx/assets/43.svg new file mode 100644 index 0000000..e4fee07 --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/43.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
符号位
最高位
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
int a = 10;
+10 的原码
+10 的反码
+10 的补码
1
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
1
1
1
1
1
1
1
1
1
1
1
1
0
1
0
1
符号位
最高位
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
int b = -10;
-10 的原码
-10 的反码
-10 的补码
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/assets/44.svg b/docs/notes/01_c-basic/02_xdx/assets/44.svg new file mode 100644 index 0000000..d536aab --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/44.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
unsigned int a = 10;
+10 
1
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
unsigned int b = -10;
-10 
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/index.md b/docs/notes/01_c-basic/02_xdx/index.md index a22d35e..04968fe 100644 --- a/docs/notes/01_c-basic/02_xdx/index.md +++ b/docs/notes/01_c-basic/02_xdx/index.md @@ -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 + +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³¹`,至于为什么,下节我们会详细分析。 +