diff --git a/docs/notes/01_c-basic/03_xdx/index.md b/docs/notes/01_c-basic/03_xdx/index.md index e18f1e9..eb3c81c 100644 --- a/docs/notes/01_c-basic/03_xdx/index.md +++ b/docs/notes/01_c-basic/03_xdx/index.md @@ -66,7 +66,7 @@ | unsigned long long(无符号长整型) | 8 字节(通常) | 0 ~2^64 -1 | | [signed] long long(有符号长整型,默认) | 8 字节(通常) | - 2^63 ~ 2^63-1 | -> [!IMPORTANT] +> [!NOTE] > > * ① 数据类型在内存中占用的存储单元(字节数),就称为该数据类型的长度(步长),如:short 占用 2 个字节的内存,就称 short 的长度(步长)是 2。 > diff --git a/docs/notes/01_c-basic/07_xdx/assets/1.png b/docs/notes/01_c-basic/07_xdx/assets/1.png deleted file mode 100644 index 338dd78..0000000 Binary files a/docs/notes/01_c-basic/07_xdx/assets/1.png and /dev/null differ diff --git a/docs/notes/01_c-basic/07_xdx/assets/2.png b/docs/notes/01_c-basic/07_xdx/assets/2.png deleted file mode 100644 index b4bb077..0000000 Binary files a/docs/notes/01_c-basic/07_xdx/assets/2.png and /dev/null differ diff --git a/docs/notes/01_c-basic/07_xdx/assets/3.png b/docs/notes/01_c-basic/07_xdx/assets/3.png deleted file mode 100644 index b67e43c..0000000 Binary files a/docs/notes/01_c-basic/07_xdx/assets/3.png and /dev/null differ diff --git a/docs/notes/01_c-basic/07_xdx/index.md b/docs/notes/01_c-basic/07_xdx/index.md index 8b48268..0c91cb1 100644 --- a/docs/notes/01_c-basic/07_xdx/index.md +++ b/docs/notes/01_c-basic/07_xdx/index.md @@ -13,7 +13,7 @@ > [!NOTE] > -> 之所以指针在 C 语言中颇具争议,是因为一方面其功能强大,直接操作内存地址;另一方面,又很危险,不正确的使用指针的方式,非常容易导致程序崩溃。 +> 之所以指针在 C 语言中颇具争议,是因为一方面其功能强大,直接操作内存地址;另一方面,又很危险,不正确的使用指针,非常容易导致程序崩溃。 * 如果没有能很好的使用指针,就会带来一系列的问题,如: * ① `空指针引用`(Null Pointer Dereference):当一个指针没有正确初始化或者被赋予了空(NULL)值时,如果程序尝试访问该指针所指向的内存,会导致运行时错误,甚至导致程序崩溃。 @@ -53,164 +53,14 @@ > [!IMPORTANT] > -> 总而言之,各种编程语言通过引入不同的策略和机制,如:智能指针、垃圾回收器、所有权和借用,以及强类型系统,有效地减少了指针操作所带来的各种安全性和可靠性问题,提升了程序的稳定性和开发效率。 +> * ① 总而言之,现代化的高级编程语言通过引入不同的策略和机制,如:智能指针、垃圾回收器、所有权和借用,以及强类型系统,有效地减少了指针操作所带来的各种安全性和可靠性问题,提升了程序的稳定性和开发效率。 +> * ② 换言之,现代化的高级编程语言就是在某些方面,如:性能(运行效率)、底层控制(隐藏了许多底层实现细节,以防止程序员意外地引入安全漏洞)和平台特定优化(屏蔽底层硬件细节,如:CPU 寄存器、具体的内存布局,以达到跨平台的目的,这也限制了程序员对底层优化的控制),做出一定的牺牲,以换取开发效率以及程序的稳定性。 -# 第二章:回顾知识 +# 第二章:指针的理解和定义(⭐) -## 2.1 变量 - -* 变量就是保存程序运行过程中临时产生的值,其语法如下: - -```c -数据类型 变量名 = 值 ; -``` - -> [!IMPORTANT] -> -> 变量名(标识符)需要符合命名规则和命名规范!!! -> -> * 强制规范: -> - ① 只能由`小写`或`大写英文字母`,`0-9` 或 `_` 组成。 -> - ② 不能以`数字`开头。 -> - ③ 不可以是`关键字`。 -> - ④ 标识符具有`长度`限制,不同编译器和平台会有所不同,一般限制在 63 个字符内。 -> - ⑤ 严格`区分大小写字母`,如:Hello、hello 是不同的标识符。 -> * 建议规范: -> - ① 为了提高阅读性,使用有意义的单词,见名知意,如:sum,name,max,year 等。 -> - ② 使用下划线连接多个单词组成的标识符,如:max_classes_per_student 等。 -> - ③ 多个单词组成的标识符,除了使用下划线连接,也可以使用小驼峰命名法,除第一个单词外,后续单词的首字母大写,如: studentId、student_name 等。 -> - ④ 不要出现仅靠大小写区分不同的标识符,如:name、Name 容易混淆。 -> - ⑤ 系统内部使用了一些下划线开头的标识符,如:C99 标准添加的类型 `_Bool`,为防止冲突,建议开发者尽量避免使用下划线开头的标识符。 - -* `变量名`的`作用`,如下所示: - * ① 当我们`编写`代码的时候,使用`变量名`来`关联`某块内存的`地址`。 - * ② 当 CPU `执行`的时候,会将变量名`替换`为具体的地址,再进行具体的操作。 - -## 2.2 普通变量和指针变量的区别 - -* 根据`变量`中`存储`的`值`的`不同`,我们可以将`变量`分为两类: - - `普通变量`:变量所对应的内存中存储的是`普通值`。 - - `指针变量`:变量所对应的内存中存储的是`另一个变量的地址`。 -* 如下图所示: - -![img](./assets/1.png) - -* 普通变量和指针变量的相同点,如下所示: - * ① 普通变量有内存空间,指针变量也有内存空间。 - * ② 普通变量有内存地址,指针变量也有内存地址。 - * ③ 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。 -* 普通变量和指针变量的不同点: - - ① `普通变量`所对应的内存空间`存储`的是`普通的值`,如:整数、小数、字符等;`指针变量`所对应的内存空间`存储`的是另外一个变量的`地址`。 - - ② `普通变量有普通变量的运算方式`,而`指针变量有指针变量的运算方式`(后续讲解)。 - -## 2.3 运算符 - -### 2.3.1 概述 - -* 运算符是一种特殊的符号,用于数据的运算、赋值和比较等。 -* `表达式`指的是一组运算数、运算符的组合,表达式`一定具有值`,一个变量或一个常量可以是表达式,变量、常量和运算符也可以组成表达式,如: - -![img](./assets/2.png) - -- `操作数`指的是`参与运算`的`值`或者`对象`,如: - -![](./assets/3.png) - -* 根据`操作数`的`个数`,可以将运算符分为: - * 一元运算符(一目运算符)。 - * 二元运算符(二目运算符)。 - * 三元运算符(三目运算符)。 -* 根据`功能`,可以将运算符分为: - * 算术运算符。 - * 关系运算符(比较运算符)。 - * 逻辑运算符。 - * 赋值运算符。 - * 逻辑运算符。 - * 位运算符。 - * 三元运算符。 - -> [!NOTE] -> -> 掌握一个运算符,需要关注以下几个方面: -> -> - ① 运算符的含义。 -> - ② 运算符操作数的个数。 -> - ③ 运算符所组成的表达式。 -> - ④ 运算符有无副作用,即:运算后是否会修改操作数的值。 - -> [!IMPORTANT] -> -> 普通变量支持上述的所有运算符;而指针变量并非支持上述的所有运算符,且支持运算符的含义和普通变量相差较大!!! - -### 2.3.2 运算符的优先级 - -* C 语言中运算符的优先级,如下所示: - -| **优先级** | **运算符** | **名称或含义** | **结合方向** | -| ---------- | ---------- | ---------------- | ------------- | -| **1** | `[]` | 数组下标 | ➡️(从左到右) | -| | `()` | 圆括号 | | -| | `.` | 成员选择(对象) | | -| | `->` | 成员选择(指针) | | -| **2** | `-` | 负号运算符 | ⬅️(从右到左) | -| | `(类型)` | 强制类型转换 | | -| | `++` | 自增运算符 | | -| | `--` | 自减运算符 | | -| | `*` | 取值运算符 | | -| | `&` | 取地址运算符 | | -| | `!` | 逻辑非运算符 | | -| | `~` | 按位取反运算符 | | -| | `sizeof` | 长度运算符 | | -| **3** | `/` | 除 | ➡️(从左到右) | -| | `*` | 乘 | | -| | `%` | 余数(取模) | | -| **4** | `+` | 加 | ➡️(从左到右) | -| | `-` | 减 | | -| **5** | `<<` | 左移 | ➡️(从左到右) | -| | `>>` | 右移 | | -| **6** | `>` | 大于 | ➡️(从左到右) | -| | `>=` | 大于等于 | | -| | `<` | 小于 | | -| | `<=` | 小于等于 | | -| **7** | `==` | 等于 | ➡️(从左到右) | -| | `!=` | 不等于 | | -| **8** | `&` | 按位与 | ➡️(从左到右) | -| **9** | `^` | 按位异或 | ➡️(从左到右) | -| **10** | `\|` | 按位或 | ➡️(从左到右) | -| **11** | `&&` | 逻辑与 | ➡️(从左到右) | -| **12** | `\|\|` | 逻辑或 | ➡️(从左到右) | -| **13** | `?:` | 条件运算符 | ⬅️(从右到左) | -| **14** | `=` | 赋值运算符 | ⬅️(从右到左) | -| | `/=` | 除后赋值 | | -| | `*=` | 乘后赋值 | | -| | `%=` | 取模后赋值 | | -| | `+=` | 加后赋值 | | -| | `-=` | 减后赋值 | | -| | `<<=` | 左移后赋值 | | -| | `>>=` | 右移后赋值 | | -| | `&=` | 按位与后赋值 | | -| | `^=` | 按位异或后赋值 | | -| | `\|=` | 按位或后赋值 | | -| **15** | `,` | 逗号运算符 | ➡️(从左到右) | - -> [!WARNING] -> -> * ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量`使用小括号来控制`表达式的执行顺序。 -> * ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它`分成几步`来完成。 -> * ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。 - -> [!IMPORTANT] -> -> * ① 取值运算符 `*` 和取地址运算符 `&` 的优先级相同,并且运算方向都是从右向左!!! -> * ② 逗号运算符 `,` 的优先级最低,并且运算方向是从左向右!!! - - - -# 第三章:指针的理解和定义(⭐) - -## 3.1 变量的访问方式 +## 2.1 变量的访问方式 * 计算机中程序的运行都是在内存中进行的,变量也是内存中分配的空间,且不同类型的变量占据的内存空间大小不同,如:char 类型的变量是 1 个字节,short 类型的变量是 2 个字节,int 类型的变量是 4 个字节... * 之前我们都是通过`变量名(普通变量)`访问内存中存储的数据,如下所示: @@ -243,7 +93,7 @@ int main() { > * ① 我们通过`变量名(普通变量)`访问内存中变量存储的数据,之所以称为`直接访问`的方式,是因为对于我们写程序而言,我们无需关心如何根据内存地址去获取内存中对应的数据,也无需关系如何根据内存地址将数据存储到对应的内存空间,这些操作步骤都是`编译器`帮助我们在底层自动完成的(自动化)。 > * ② 但是,我们也可以通过`内存地址`去操作内存中对应的数据(手动化),这种方式就称为`间接访问`的方式了,相对于`直接访问`方式来说,要`理解`的`概念`和`操作`的`步骤`和之前`直接访问`的方式相比,要复杂和麻烦很多,但是效率高。 -## 3.2 内存地址和指针 +## 2.2 内存地址和指针 * 其实,在之前《数组》中,我们就已经讲解了`内存地址`的概念了,即:操作系统为了更快的去管理内存中的数据,会将`内存条`按照`字节`划分为一个个的`单元格`,并为每个独立的小的`单元格`,分配`唯一的编号`,即:`内存地址`,如下所示: @@ -302,13 +152,13 @@ int main() { > > 如果你观察仔细的话,你可能会发现`指针变量`和`普通变量`在内存中占据的存储空间是不一样的,那么到底是什么原因造成这样的结果? -## 3.3 指针变量的定义 +## 2.3 指针变量的定义 -## 3.4 指针的作用 +## 2.4 指针的作用 * 查询数据。 * 存储数据。 @@ -404,15 +254,15 @@ int main() { -# 第四章:指针的运算(⭐) +# 第三章:指针的运算(⭐) -## 4.1 概述 +## 3.1 概述 -## 4.2 总结 +## 3.2 总结 * 在 C 语言中,`普通变量`是直接存储`数据`的`变量`。对于普通变量,支持的操作包括: * ① **赋值操作**:给变量赋值,如:`int a = 5`。