mirror of
https://github.com/Aexiar/c.git
synced 2024-10-22 14:05:45 +02:00
c
This commit is contained in:
parent
b2da313b26
commit
8c9894d099
@ -1177,13 +1177,13 @@ int main() {
|
||||
* 规则:
|
||||
* 正数的`原码`是它本身对应的二进制数,符号位是 0 。
|
||||
* 负数的`原码`是它本身绝对值对应的二进制数,但是符号位是 1 。
|
||||
* +1 的原码,使用 `16` 位二进数来表示,就是:
|
||||
* `+1` 的原码,使用 `16` 位二进数来表示,就是:
|
||||
|
||||
| 十进制数 | 原码(16位二进制数) |
|
||||
| -------- | --------------------- |
|
||||
| +1 | `0`000 0000 0000 0001 |
|
||||
|
||||
* -1 的原码,使用 `16` 位二进数来表示,就是:
|
||||
* `-1` 的原码,使用 `16` 位二进数来表示,就是:
|
||||
|
||||
| 十进制数 | 原码(16位二进制数) |
|
||||
| -------- | --------------------- |
|
||||
@ -1203,13 +1203,13 @@ int main() {
|
||||
* 正数的反码和它的原码相同。
|
||||
* 负数的反码是在其原码的基础上,符号位不变,其余各位取反。
|
||||
|
||||
* +1 的反码,使用 `16` 位二进数来表示,就是:
|
||||
* `+1` 的反码,使用 `16` 位二进数来表示,就是:
|
||||
|
||||
| 十进制数 | 原码(16位二进制数) | 反码(16位二进制数) |
|
||||
| -------- | --------------------- | --------------------- |
|
||||
| +1 | `0`000 0000 0000 0001 | `0`000 0000 0000 0001 |
|
||||
|
||||
* -1 的反码,使用 `16` 位二进数来表示,就是:
|
||||
* `-1` 的反码,使用 `16` 位二进数来表示,就是:
|
||||
|
||||
| 十进制数 | 原码(16位二进制数) | 反码(16位二进制数) |
|
||||
| -------- | --------------------- | --------------------- |
|
||||
@ -1219,7 +1219,7 @@ int main() {
|
||||
>
|
||||
> 总结:
|
||||
>
|
||||
> * ① 按照反码的规则,如果是 `+0`,对应的原码是 `0`000 0000 0000 0000;那么,其反码还是 `0`000 0000 ;如果是 `-0`,对应的原码是 `1`000 0000 0000 0000,其反码是 `1`111 1111 1111 1111,显然不符合实际情况。
|
||||
> * ① 按照反码的规则,如果是 `+0`,对应的原码是 `0`000 0000 0000 0000;那么,其反码还是 `0`000 0000 0000 0000;如果是 `-0`,对应的原码是 `1`000 0000 0000 0000,其反码是 `1`111 1111 1111 1111,显然不符合实际情况。
|
||||
> * ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是反码。
|
||||
|
||||
### 3.5.4 补码
|
||||
@ -1228,13 +1228,13 @@ int main() {
|
||||
|
||||
* 正数的补码和它的原码相同。
|
||||
* 负数的补码是在其反码的基础上 + 1 。
|
||||
* +1 的补码,使用 `16` 位二进数来表示,就是:
|
||||
* `+1` 的补码,使用 `16` 位二进数来表示,就是:
|
||||
|
||||
| 十进制数 | 原码(16位二进制数) | 反码(16位二进制数) | 补码(16位二进制数) |
|
||||
| -------- | --------------------- | -------------------- | -------------------- |
|
||||
| +1 | `0`000 0000 0000 0001 | 0000 0000 0000 0001 | 0000 0000 0000 0001 |
|
||||
| -------- | --------------------- | --------------------- | --------------------- |
|
||||
| +1 | `0`000 0000 0000 0001 | `0`000 0000 0000 0001 | `0`000 0000 0000 0001 |
|
||||
|
||||
* -1 的补码,使用 `16` 位二进数来表示,就是:
|
||||
* `-1` 的补码,使用 `16` 位二进数来表示,就是:
|
||||
|
||||
| 十进制数 | 原码(16位二进制数) | 反码(16位二进制数) | 补码(16位二进制数) |
|
||||
| -------- | --------------------- | --------------------- | --------------------- |
|
||||
@ -1258,7 +1258,7 @@ int main() {
|
||||
>
|
||||
> * ① 补码表示法解决了`原码`和`反码`存在的`两种`零(`+0` 和 `-0`)的问题,即:在补码表示法中,只有`一个`零,即 `0000 0000`。
|
||||
> * ②补码使得`加法运算`和`减法运算`可以统一处理,通过将减法运算`转换`为加法运算,可以简化硬件设计,提高了运算效率。
|
||||
> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。换言之,当`读取`整数的时候,需要采用`逆向`的转换,即:将补码转换为原码。正数的原码、反码、补码都是一样的,三码合一。负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码。
|
||||
> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。换言之,当`读取`整数的时候,需要采用`逆向`的转换,即:将补码转换为原码。正数的原码、反码、补码都是一样的,三码合一。负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码(符号位是不能借的)。
|
||||
|
||||
### 3.5.5 总结
|
||||
|
||||
@ -1379,5 +1379,5 @@ int main() {
|
||||
>
|
||||
> * ① 实际开发中,`printf` 函数中的常量、变量或表达式,需要和格式占位符一一对应;否则,将会出现数据错误的现象。
|
||||
> * ② 正因为上述的原因,很多现代化的编程语言,如:Java 等,直接取消了无符号的概念。但是,很多数据库是使用 C 语言开发的,如:MySQL 等,就提供了创建数据表的字段为无符号类型的功能,即:`UNSIGNED`(正整数) ,不要感觉困惑!!!
|
||||
> * ③ 对于 `1000 0000 …… 0000 0000` 这个特殊的补码,无法按照上述的方法转换为原码(假设补码是 1000 0000 0000 0000,按照补码表示法,它的反码就是 0111 1111 1111 1111,它的原码就是 1000 0000 0000 0000,会发现 1000 0000 0000 0000 的补码和原码是一致的;换言之,1000 0000 0000 0000 没有对应的常规原码表示,它本身就是补码表示,无法转换为原码),所以计算机直接规定这个补码对应的值就是 `-2³¹`,至于为什么,下节我们会详细分析。
|
||||
> * ③ 对于 `1000 0000 …… 0000 0000` 这个特殊的补码,无法按照上述的方法转换为原码,所以计算机直接规定这个补码对应的值就是 `-2³¹`,至于为什么,下节我们会详细分析。
|
||||
|
||||
|
BIN
docs/notes/01_c-basic/03_xdx/assets/0.jpg
Normal file
BIN
docs/notes/01_c-basic/03_xdx/assets/0.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
BIN
docs/notes/01_c-basic/03_xdx/assets/1.webp
Normal file
BIN
docs/notes/01_c-basic/03_xdx/assets/1.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
4
docs/notes/01_c-basic/03_xdx/assets/无符号的取值范围1.drawio.svg
Normal file
4
docs/notes/01_c-basic/03_xdx/assets/无符号的取值范围1.drawio.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 82 KiB |
4
docs/notes/01_c-basic/03_xdx/assets/无符号的取值范围2.drawio.svg
Normal file
4
docs/notes/01_c-basic/03_xdx/assets/无符号的取值范围2.drawio.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 220 KiB |
@ -593,24 +593,130 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2.9 数值溢出
|
||||
## 1.3 数值溢出
|
||||
|
||||
* 所谓的数值溢出指的是:当超过一个数据类型能够存放的最大范围的时候,数值就会溢出。
|
||||
* 如果达到了最大值,再进行加法计算,数据就会超过该类型能够表示的最大值,叫做上溢出。
|
||||
* 如果这个数目前是最小值,再进行减法计算, 数据就会超过该类型的最小值, 叫做下溢出。
|
||||
### 1.3.1 概述
|
||||
|
||||
* 在 C 语言中,`整数`的`数据类型`分为`无符号`和`有符号`的,其在底层表示和存储是不一样的,即:
|
||||
* `无符号整数不使用最高位作为符号位`,所有的位都用于表示数值,如:对于一个 4 位无符号整数,二进制表示的范围是从 0000 到 1111 ,那么十进制表示的范围是从 0 到 15。
|
||||
* `有符号整数使用最高位作为符号位`,这意味着它们可以表示正数和负数,通常使用补码来表示有符号整数。在补码表示法中:最高位为 0 表示正数、最高位为 1 表示负数,如:对于一个4位有符号整数,二进制表示的范围是从 0000(0) 到 0111 (7),1000 (-8)到 1111(-1)。
|
||||
* 在生活中,如果一个容器的容量是固定的,我们不停的向其中注入水,那么当容器中充满水之后,继续注入,就会溢出,如下所示:
|
||||
|
||||
![](./assets/0.jpg)
|
||||
|
||||
* 在程序中也是一样的,各种整数类型在内存中占用的存储单元是不同的,如:short 在内存中占用 2 个字节的存储单元,int 在内存中占用 4 个字节的存储单元。这也就意味着,各种整数类型只能存储有限的数值,当数值过大或多小的时候,超出的部分就会被直接截掉,那么数值就不能正确的存储,我们就将这种现象就称为`溢出`(overflow)。
|
||||
* 如果达到了最大值,再进行加法计算,数据就会超过该类型能够表示的最大值,叫做`上溢出`。
|
||||
* 如果这个数目前是最小值,再进行减法计算, 数据就会超过该类型的最小值, 叫做`下溢出`。
|
||||
|
||||
### 1.3.2 无符号数的取值范围
|
||||
|
||||
* 在 C 语言中,`无符号数`(unsigned 类型)的取值范围(最大值和最小值)的计算是很容易的,即:将内存中的所有位,设置为 `0` 就是`最小值`,设置为 `1` 就是`最大值`。
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 在 C 语言中,无符号整数,最高位不是符号位,它是数值的一部分。
|
||||
|
||||
* 以 `unsigned char` 类型为例,它在内存中占用的存储单元是 1 个字节,即 8 位。如果所有位都设置为 `0` ,它的最小值就是 `0` ;如果所有位设置为 `1` ,它的最大值就是 `2⁸ - 1 = 255` ,如下所示:
|
||||
|
||||
![](./assets/无符号的取值范围1.drawio.svg)
|
||||
|
||||
* 那么,`unsigned char` 的最大值是如何计算出来的?最简单的方法就是这样的,如下所示:
|
||||
|
||||
```txt
|
||||
1 × 2⁰ + 1 × 2¹ + 1 × 2² + 1 × 2³ + 1 × 2⁴ + 1 × 2⁵ + 1 × 2⁶ + 1 × 2⁷
|
||||
= 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128
|
||||
= 255
|
||||
```
|
||||
|
||||
* 但是,这种计算方法虽然有效,但是非常麻烦,如果是 8 个字节的 long ,那么计算就非常麻烦了(可能要计算半天)。当然,我们也知道,这就是等比数列(高中知识),等比数列的公式,如下所示:
|
||||
|
||||
$S_n = a_1 \times \frac{1 - r^n}{1 - r}$
|
||||
|
||||
* 那么,结果就是:$S_8 = 1 \times \frac{1 - 2^8}{1 - 2} = \frac{1 - 256}{-1} = 255$
|
||||
|
||||
* 但是,貌似还是很复杂,我们可以换个思路,就是让 `1111 1111` 先 `+1` ,然后再 `-1`,这样一增一减正好抵消掉,并且不会影响最终的结果,如下所示:
|
||||
|
||||
```txt
|
||||
1111 1111 + 1 - 1
|
||||
= 10000 0000 - 1
|
||||
= 2⁹⁻¹ - 1
|
||||
= 2⁸ - 1
|
||||
= 255
|
||||
```
|
||||
|
||||
* 其对应的换算过程,如下所示:
|
||||
|
||||
![](./assets/无符号的取值范围2.drawio.svg)
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> * ① 当内存中所有的位都是 1 的时候,这种“凑整”的技巧非常实用!!!
|
||||
> * ② 按照上述的技巧,我们可以很容易得计算出:
|
||||
> * `unsinged char`(1 个字节) 的取值范围是:`[0, 2⁸ - 1]`。
|
||||
> * `unsinged short`(2 个字节)的取值范围是:`[0, 2¹⁶ - 1]`。
|
||||
> * `unsinged int`(4 个字节)的取值范围是:`[0, 2³² - 1]`。
|
||||
> * `unsinged long`(8 个字节)的取值范围是:`[0, 2⁶⁴ - 1]`。
|
||||
|
||||
### 1.3.3 有符号数的取值范围
|
||||
|
||||
* 在 C 语言中,`有符号数`(signed 类型)在计算机底层是以`补码`的形式存储的(计算的时候,也是以补码的形式进行计算的,并且符号位参与计算);但是,在读取的时候,需要采用`逆向`的转换,即:将补码转换为原码。
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 在 C 语言中,有符号整数,最高位是符号位,用于表示正负数。
|
||||
|
||||
* 以 `char` 类型为例,它的取值范围,如下所示:
|
||||
|
||||
| 补码 | 反码 | 原码 | 值 |
|
||||
| ------------- | --------- | --------- | -------- |
|
||||
| 1111 1111 | 1111 1110 | 1000 0001 | -1 |
|
||||
| 1111 1110 | 1111 1101 | 1000 0010 | -2 |
|
||||
| 1111 1101 | 1111 1100 | 1000 0011 | -3 |
|
||||
| ... | ... | ... | ... |
|
||||
| 1000 0011 | 1000 0010 | 1111 1101 | -125 |
|
||||
| 1000 0010 | 1000 0001 | 1111 1110 | -126 |
|
||||
| 1000 0001 | 1000 0000 | 1111 1111 | -127 |
|
||||
| **1000 0000** | **---** | **---** | **-128** |
|
||||
| 0111 1111 | 0111 1111 | 0111 1111 | 127 |
|
||||
| 0111 1110 | 0111 1110 | 0111 1110 | 126 |
|
||||
| 0111 1101 | 0111 1101 | 0111 1101 | 125 |
|
||||
| ... | ... | ... | ... |
|
||||
| 0000 0010 | 0000 0010 | 0000 0010 | 2 |
|
||||
| 0000 0001 | 0000 0001 | 0000 0001 | 1 |
|
||||
| 0000 0000 | 0000 0000 | 0000 0000 | 0 |
|
||||
|
||||
* 从上面的列表中,我们可以得知,`char` 类型的取值范围是:`[-2⁸, 2⁸ - 1]`,即:`[-128, 127]`。
|
||||
* 对于 `-128` 而言,它的补码是 `1000 0000`,是无法按照传统的补码表示法来计算原码的,因为在补码转换到反码的时候需要 `-1` ,而 `1000 0000 - 1`需要向高位借 `1` ,而最高位是符号位是不能借的,这就非常矛盾。
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 计算机规定,`1000 0000` 这个特殊的补码就表示 `-128` 。
|
||||
|
||||
* 但是,为什么偏偏是 `-128` ,而不是其它数字?是因为 `-128` 使得 `char` 类型的取值范围保持连贯,中间没有“空隙”。如果我们按照传统的方式来计算 `-128` 的补码,如下所示:
|
||||
* ① 原码:在原码表示法中,-128 的数据位是 `1000 0000`,但是 char 的数据位只有 `7` 位,那么最高位 `1` 就变为了符号位,剩下的数据位就是 `000 0000`;所以,`-128` 的原码就是 `1000 0000`。
|
||||
* ② 反码:对数据位取反,-128 的反码就是:`1111 1111` 。
|
||||
* ③ 补码:在反码的基础上 `+1`,得到 `1000 0000`,是因为符号位被覆盖了,补码最终依然是 `1000 0000`。
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> * 在 C 语言中,无符号整数,最高位不是符号位,它是数值的一部分。
|
||||
> * 在 C 语言中,有符号整数,最高位是符号位,用于表示正负数。
|
||||
> `-128` 从原码转换到补码的过程中,符号位被 `1` 覆盖了两次,而负数的符号位本来就是 `1`,被 `1` 覆盖多少次也不会影响到数字的符号。
|
||||
|
||||
* 虽然从 `1000 0000` 这个补码推算不出 `-128`,但是从 `-128` 却能推算出 `1000 0000` 这个补码,即:有符号数在存储之前先要转换为补码。
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> * ① 通过这种方式,`-128` 就成为了补码的最小值 `1000 0000`,而这个值不会与其他任何正数或负数的补码冲突。
|
||||
> * 如果采用原码存储,那么将会出现 `+0` 和 `-0` 的情况,即:`0000 0000`、`1000 0000`,这样在取值范围就存在两个相同的值,多此一举。
|
||||
> * 如果采用原码存储,最大值不变是 `127` ,但是最小值只能存储到 `-127` ,因为 `-128` 的原码是 `1000 0000`和 `-0` 的原码冲突。
|
||||
> * ② 这就是补码系统的强大之处,它能让整数的范围连贯,并且实现了加法和减法的统一处理。
|
||||
> * ③ 按照上述的方法,我们可以很容易得计算出:
|
||||
> * `char`(1 个字节) 的取值范围是:`[-2⁸, 2⁸ - 1]`。
|
||||
> * `short`(2 个字节)的取值范围是:`[-2¹⁶, 2¹⁶ - 1]`。
|
||||
> * `int`(4 个字节)的取值范围是:`[-2³², 2³² - 1]`。
|
||||
> * `long`(8 个字节)的取值范围是:`[-2⁶⁴, 2⁶⁴ - 1]`。
|
||||
|
||||
### 1.3.4 数值溢出
|
||||
|
||||
* 对于无符号的数值溢出:
|
||||
* 当数据到达最大值的时候,再加 1 就会回到无符号数的最小值。
|
||||
* 当数据达到最小值的时候,再减 1 就会回到无符号数的最大值。
|
||||
* 当数据到达最大值的时候,再 `+1` 就会回到无符号数的最小值。
|
||||
* 当数据达到最小值的时候,再 `-1` 就会回到无符号数的最大值。
|
||||
|
||||
* 那么,无符号的上溢出,原理就是这样的:
|
||||
|
||||
@ -621,8 +727,8 @@ int main() {
|
||||
![](./assets/4.png)
|
||||
|
||||
* 对于有符号的数值溢出:
|
||||
* 当数据到达最大值的时候,再加 1 就会回到有符号数的最小值。
|
||||
* 当数据达到最小值的时候,再减 1 就会回到有符号数的最大值。
|
||||
* 当数据到达最大值的时候,再 `+1` 就会回到有符号数的最小值。
|
||||
* 当数据达到最小值的时候,再 `-1` 就会回到有符号数的最大值。
|
||||
|
||||
* 那么,有符号的上溢出,原理就是这样的:
|
||||
|
||||
@ -676,9 +782,9 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 1.3 浮点类型
|
||||
## 1.4 浮点类型
|
||||
|
||||
### 1.3.1 概述
|
||||
### 1.4.1 概述
|
||||
|
||||
* 在生活中,我们除了使用`整数`,如:18、25 之外,还会使用到`小数`,如:3.1415926、6.18 等,`小数`在计算机中也被称为`浮点数`(和底层存储有关)。
|
||||
* `整数`在计算机底层的存储被称为`定点存储`,如下所示:
|
||||
@ -710,7 +816,7 @@ int main() {
|
||||
> * 科学计数法形式:5.12e2(e 表示基数 10)、5.12E-2(E 表示基数 10)。
|
||||
> * ③ 在实际开发中,对于浮点类型,建议使用 double 类型;如果范围不够,就使用 long double 类型。
|
||||
|
||||
### 1.3.2 格式占位符
|
||||
### 1.4.2 格式占位符
|
||||
|
||||
* 对于 float 类型的格式占位符,是 `%f` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2f` 表示保留 `2` 位小数。
|
||||
* 对于 double 类型的格式占位符,是 `%lf` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2lf` 表示保留 `2` 位小数。
|
||||
@ -792,7 +898,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3.3 字面量后缀
|
||||
### 1.4.3 字面量后缀
|
||||
|
||||
* 浮点数字面量默认是 double 类型。
|
||||
* 如果需要表示 float 类型的字面量,需要后面添加后缀 f 或 F。
|
||||
@ -819,7 +925,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3.4 类型占用的内存大小(存储空间)
|
||||
### 1.4.4 类型占用的内存大小(存储空间)
|
||||
|
||||
* 可以通过 sizeof 运算符来获取 float、double 以及 long double 类型占用的内存大小(存储空间)。
|
||||
|
||||
@ -840,7 +946,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3.5 类型的取值范围
|
||||
### 1.4.5 类型的取值范围
|
||||
|
||||
* 可以通过 `#include <float.h>` 来获取类型的取值范围。
|
||||
|
||||
@ -862,9 +968,9 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 1.4 字符类型
|
||||
## 1.5 字符类型
|
||||
|
||||
### 1.4.1 概述
|
||||
### 1.5.1 概述
|
||||
|
||||
* 在生活中,我们会经常说:今天天气真 `好`,我的性别是 `女`,我今年 `10` 岁,像这类数据,在 C 语言中就可以用字符(char)来表示。
|
||||
* 在 C 语言中,变量的`字符类型`可以表示`单`个字符,如:`'1'`、`'A'`、`'&'`。
|
||||
@ -890,7 +996,7 @@ int main() {
|
||||
| `\\` | 反斜杠 |
|
||||
| ... | |
|
||||
|
||||
### 1.4.2 格式占位符
|
||||
### 1.5.2 格式占位符
|
||||
|
||||
* 在 C 语言中,使用 `%c` 来表示 char 类型。
|
||||
|
||||
@ -917,7 +1023,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.4.3 类型占用的内存大小(存储空间)
|
||||
### 1.5.3 类型占用的内存大小(存储空间)
|
||||
|
||||
* 可以通过 sizeof 运算符来获取 char 类型占用的内存大小(存储空间)。
|
||||
|
||||
@ -937,7 +1043,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.4.4 类型的取值范围
|
||||
### 1.5.4 类型的取值范围
|
||||
|
||||
* 可以通过 `#include <limits.h>` 来获取类型的取值范围。
|
||||
|
||||
@ -958,7 +1064,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.4.5 字符类型的本质
|
||||
### 1.5.5 字符类型的本质
|
||||
|
||||
* 在 C 语言中,char 本质上就是一个整数,是 ASCII 码中对应的数字,占用的内存大小是 1 个字节(存储空间),所以 char 类型也可以进行数学运算。
|
||||
|
||||
@ -1001,13 +1107,13 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 1.5 布尔类型
|
||||
## 1.6 布尔类型
|
||||
|
||||
### 1.5.1 概述
|
||||
### 1.6.1 概述
|
||||
|
||||
* 布尔值用于表示 true(真)、false(假)两种状态,通常用于逻辑运算和条件判断。
|
||||
|
||||
### 1.5.2 早期的布尔类型
|
||||
### 1.6.2 早期的布尔类型
|
||||
|
||||
* 在 C 语言标准(C89)中,并没有为布尔值单独设置一个数据类型,所以在判断真、假的时候,使用 `0` 表示 `false`(假),`非 0` 表示 `true`(真)。
|
||||
|
||||
@ -1037,7 +1143,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.5.3 宏定义的布尔类型
|
||||
### 1.6.3 宏定义的布尔类型
|
||||
|
||||
* 判断真假的时候,以 `0` 为 `false`(假)、`1` 为 `true`(真),并不直观;所以,我们可以借助 C 语言的宏定义。
|
||||
|
||||
@ -1071,7 +1177,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.5.4 C99 标准中的布尔类型
|
||||
### 1.6.4 C99 标准中的布尔类型
|
||||
|
||||
* 在 C99 中提供了 `_Bool` 关键字,用于表示布尔类型;其实,`_Bool`类型的值是整数类型的别名,和一般整型不同的是,`_Bool`类型的值只能赋值为 `0` 或 `1` (0 表示假、1 表示真),其它`非 0` 的值都会被存储为 `1` 。
|
||||
|
||||
@ -1104,7 +1210,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 1.5.5 C99 标准头文件中的布尔类型(推荐)
|
||||
### 1.6.5 C99 标准头文件中的布尔类型(推荐)
|
||||
|
||||
* 在 C99 中提供了一个头文件 `<stdbool.h>`,定义了 `bool` 代表 `_Bool`,`false` 代表 `0` ,`true` 代表 `1` 。
|
||||
|
||||
@ -1152,15 +1258,15 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 1.6 数据类型转换
|
||||
## 1.7 数据类型转换
|
||||
|
||||
### 1.6.1 概述
|
||||
### 1.7.1 概述
|
||||
|
||||
* 在 C 语言编程中,经常需要对不同类型的数据进行运算,运算前需要先转换为同一类型,再运算。为了解决数据类型不一致的问题,需要对数据的类型进行转换。
|
||||
|
||||
### 1.6.2 自动类型转换(隐式转换)
|
||||
### 1.7.2 自动类型转换(隐式转换)
|
||||
|
||||
#### 1.6.2.1 运算过程中的自动类型转换
|
||||
#### 1.7.2.1 运算过程中的自动类型转换
|
||||
|
||||
* 不同类型的数据进行混合运算的时候,会发生数据类型转换,`窄类型会自动转换为宽类型`,这样就不会造成精度损失。
|
||||
|
||||
@ -1273,7 +1379,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.6.2.2 赋值时的自动类型转换
|
||||
#### 1.7.2.2 赋值时的自动类型转换
|
||||
|
||||
* 在赋值运算中,赋值号两边量的数据类型不同时,等号右边的类型将转换为左边的类型。
|
||||
* 如果窄类型赋值给宽类型,不会造成精度损失;如果宽类型赋值给窄类型,会造成精度损失。
|
||||
@ -1342,7 +1448,7 @@ int main(){
|
||||
}
|
||||
```
|
||||
|
||||
## 1.7 再谈数据类型
|
||||
## 1.8 再谈数据类型
|
||||
|
||||
* 通过之前的知识,我们知道,CPU 是直接和内存打交道的,CPU 在处理数据的时候,会将数据临时存放到内存中。内存那么大,CPU 是怎么找到对应的数据的?
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user