Skip to content

Commit 456339d

Browse files
📝 更新C语言文档,优化条件判断和运算符优先级章节
- 删除了冗余的示例代码,简化了条件判断的描述,提升了内容的清晰度。 - 增加了运算符优先级和结合性的详细表格,增强了对运算符使用的理解。 - 调整了枚举类型的描述位置,提升了代码可读性和文档结构的逻辑性。 - 更新了内存管理和数组使用的相关内容,确保信息的准确性和实用性。
1 parent d76662f commit 456339d

File tree

4 files changed

+106
-62
lines changed

4 files changed

+106
-62
lines changed

docs/docs/选择编程语言/C/0基础语法.mdx

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ int main(){
757757

758758
* 在 C 语言中,条件成立称为“真”,条件不成立称为“假”,因此,判断条件是否成立,就是判断条件的“真假”
759759
* 怎么判断真假呢?C 语言规定,任何数值都有真假性,任何非 0 值都为“真”,只有 0 才为“假”。也就是说,108、-18、4.5、-10.5 等都是“真”,0 则是“假”
760-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/bca554bbef13027b7dabc1bb67f47a6d.png)
760+
761761

762762
- 关系运算符的运算结果只有 2 种:如果条件成立,结果就为 1,也就是“真”;如果条件不成立,结果就为 0,也就是“假”
763763

@@ -813,13 +813,6 @@ int main(){
813813
}
814814
```
815815

816-
- 练习: 计算 result 的结果
817-
818-
```c showLineNumbers
819-
int result1 = 3 > 4 + 7
820-
int result2 = (3>4) + 7
821-
int result3 = 5 != 4 + 2 * 7 > 3 == 10
822-
```
823816

824817
- 注意点:
825818
- 无论是 float 还是 double 都有精度问题, 所以一定要避免利用==判断浮点数是否相等
@@ -1110,10 +1103,30 @@ int main(){
11101103

11111104
### 运算符的优先级和结合性
11121105

1113-
- 早在小学的数学课本中,我们就学习过"从左往右,先乘除后加减,有括号的先算括号里面的", 这句话就蕴含了优先级和结合性的问题
1114-
- C 语言中,运算符的运算优先级共分为 15 级。1 级最高,15 级最低
1115-
1116-
* 在 C 语言表达式中,不同优先级的运算符, 运算次序按照由高到低执行
1117-
* 在 C 语言表达式中,相同优先级的运算符, 运算次序按照结合性规定的方向执行
1118-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/56c97e103145e96707a17273cebcdf6a.png)![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/89de357c15677f49a7316c497a6d3fc7.png)
1106+
早在小学的数学课本中,我们就学习过"从左往右,先乘除后加减,有括号的先算括号里面的", 这句话就蕴含了优先级和结合性的问题。
1107+
1108+
C 语言中,运算优先级1 级最高,15 级最低。相同优先级的运算符, 运算次序按照结合性规定的方向执行。
1109+
1110+
| 优先级 | 运算符 | 说明 | 结合性 |
1111+
| ------ | ------ | ---- | ------ |
1112+
| 1 | `()` `[]` `->` `.` | 圆括号(函数调用)、下标引用、指向结构体成员、结构体成员 | 从左到右 |
1113+
| 2 | `!` `~` `++` `--` `+` `-` `*` `&` `sizeof` `(type)` | 逻辑非、按位取反、自增自减、正负号、指针、取地址、长度、强制类型转换 | 从右到左 |
1114+
| 3 | `*` `/` `%` | 乘法、除法、取余 | 从左到右 |
1115+
| 4 | `+` `-` | 加法、减法 | 从左到右 |
1116+
| 5 | `<<` `>>` | 左移、右移 | 从左到右 |
1117+
| 6 | `<` `<=` `>` `>=` | 小于、小于等于、大于、大于等于 | 从左到右 |
1118+
| 7 | `==` `!=` | 等于、不等于 | 从左到右 |
1119+
| 8 | `&` | 按位与 | 从左到右 |
1120+
| 9 | `^` | 按位异或 | 从左到右 |
1121+
| 10 | `\|` | 按位或 | 从左到右 |
1122+
| 11 | `&&` | 逻辑与 | 从左到右 |
1123+
| 12 | `\|\|` | 逻辑或 | 从左到右 |
1124+
| 13 | `?:` | 条件运算符(三目运算符) | 从右到左 |
1125+
| 14 | `=` `+=` `-=` `*=` `/=` `%=` `&=` `^=` `\|=` `<<=` `>>=` | 各种赋值运算符 | 从右到左 |
1126+
| 15 | `,` | 逗号运算符 | 从左到右 |
1127+
1128+
:::tip 记忆技巧
1129+
1. 复杂表达式推荐使用括号`()`来明确运算顺序,提高代码可读性。
1130+
2. **大部分运算符从左到右**,只有单目运算符、三目运算符、赋值运算符是**从右到左**
1131+
:::
11191132

docs/docs/选择编程语言/C/1变量.mdx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,6 @@ int main(){
111111

112112
### enum
113113

114-
枚举的类型的主要作用是提高代码的可读性。枚举在本质上更接近`#define`定义的整型常量,不支持浮点数和数组,多用作常量集合。了解基本使用即可。
115-
116-
枚举主要是通过标识符赋值让你原本的数组更便于理解,你可以理解为`#define`的升级版。
117-
118-
<Highlight color="#96cf54">枚举类型是基本数据类型(非构造类型),表示有限集合的特殊类型,</Highlight>
119-
120114
在实际生活中,有些变量的取值被限定在一个确定的范围内。例如:考试评分等级为A、B、C。星期的范围是1-7。
121115

122116
“枚举”类型的定义中列举出所有可能的取值, 被说明为该“枚举”类型的变量取值不能超过定义的范围。
@@ -126,6 +120,10 @@ int main(){
126120
* 也可以在定义枚举类型时改变枚举元素的值
127121
* 枚举内已经用过的标识符名称不能再用。
128122

123+
枚举的类型的主要作用是提高代码的可读性。枚举在本质上更接近`#define`定义的整型常量,不支持浮点数和数组,多用作常量集合。了解基本使用即可。
124+
125+
<Highlight color="#96cf54">枚举类型是基本数据类型(非构造类型),表示有限集合的特殊类型</Highlight>。
126+
129127
枚举类型的定义格式:
130128

131129
```c showLineNumbers
@@ -174,10 +172,28 @@ int main(int argc, const char * argv[]) {
174172
}
175173
```
176174
177-
#### 枚举类型变量的赋值和使用
175+
:::tip
176+
枚举的最佳实践
177+
178+
枚举的最佳实践是使用typedef关键字定义枚举类型,这样可以提高代码的可读性。
178179
179180
```c showLineNumbers
181+
typedef enum {
182+
STATE_A,
183+
STATE_B
184+
} StateType;
185+
186+
// 此时state的类型为StateType,就和你使用int、double、char等类型一样
187+
StateType state = STATE_A;
188+
```
189+
:::
190+
191+
192+
:::warning
193+
194+
下面是一些不推荐的写法,因为它们可能会导致代码的可读性变差。
180195

196+
```c showLineNumbers
181197
enum Season {
182198
Spring,
183199
Summer,
@@ -187,21 +203,20 @@ enum Season {
187203

188204
//等价于 enum Season s;
189205

190-
191206
s = Spring; // 等价于 s = 0;
192207
// 也可以赋值为枚举元素以外的值
193208
s = 3; // 等价于 s = winter;
194209
printf("%d", s);
195210

196211

197212
// 枚举变量可以省略类型,直接赋值
213+
// 没有给枚举类型命名,只能在定义时创建变量(不推荐)
198214
enum {
199215
A,
200216
B,
201217
} Num;
202-
203218
```
204-
219+
:::
205220
206221
207222
## 作用域

docs/docs/选择编程语言/C/2数据.mdx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,7 @@ int main(){
6060

6161
`char``int`类型转换时,`int`转为`char`时会是对应的`ASCII`码表中字符。`char`转为`int`时会是对应的`ASCII`码表中对应的数字。
6262

63-
64-
ASCII 表
65-
66-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/b519ba9d45ab584c43c991777d8e978a.png)
63+
ASCII 表完整内容可以查看:[https://www.asciitable.com/](https://www.asciitable.com/)
6764

6865
:::tip
6966
想要存储中文可以用字符串数组。

docs/docs/选择编程语言/C/7构造数据.mdx

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -150,43 +150,63 @@ int main() {
150150

151151
```
152152

153-
- 内存寻址从大到小, 从高地址开辟一块连续没有被使用的内存给数组
153+
- 内存寻址从大到小, **系统**从高地址开辟一块连续没有被使用的(栈)内存给数组
154154
- 从分配的连续存储空间中, 地址小的位置开始给每个元素分配空间
155-
- 从每个元素分配的存储空间中, 地址最大的位置开始存储数据
156-
- 用数组名指向整个存储空间最小的地址
157-
155+
- 数组名指向整个存储空间最小的地址
158156

159157
```c showLineNumbers
160158
#include <stdio.h>
161159
int main()
162160
{
163-
int num = 9;
164-
char cs[] = {'l','n','j'};
165-
printf("cs = %p\n", &cs); // cs = 0060FEA9
166-
printf("cs[0] = %p\n", &cs[0]); // cs[0] = 0060FEA9
167-
printf("cs[1] = %p\n", &cs[1]); // cs[1] = 0060FEAA
168-
printf("cs[2] = %p\n", &cs[2]); // cs[2] = 0060FEAB
169-
170-
int nums[] = {2, 6};
171-
printf("nums = %p\n", &nums); // nums = 0060FEA0
172-
printf("nums[0] = %p\n", &nums[0]);// nums[0] = 0060FEA0
173-
printf("nums[1] = %p\n", &nums[1]);// nums[1] = 0060FEA4
174-
161+
char cs[] = {'l','n','j'}; // 获得三个高地址。假设为:99、98、97
162+
// 数组名指向整个存储空间最小的地址
163+
printf("cs = %p\n", &cs); // cs = 97
164+
// 数组元素指向每个元素的地址
165+
// 从分配的连续存储空间中, 地址小的位置开始给每个元素分配空间
166+
printf("cs[0] = %p\n", &cs[0]); // cs[0] = 97
167+
printf("cs[1] = %p\n", &cs[1]); // cs[1] = 98
168+
printf("cs[2] = %p\n", &cs[2]); // cs[2] = 99
175169
return 0;
176170
}
177171
```
178172

179-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/e0aa63f597f92632c90cd1c5f6adc292.png)
180173

181-
> - 注意:字符在内存中是以对应 ASCII 码值的二进制形式存储的,而非上述的形式。
174+
:::info
175+
系统自动分配的内存空间叫做栈。从高地址开始,依次向下分配。默认 1-8 MB。可调整到几十MB,但不宜太大,因为每个线程都需要独立堆区(不用也占着),多线程会占用大量内存。
176+
177+
那么我们程序员则可以从下往上使用内存。叫做堆。使用堆时,系统不会自动分配内存,需要我们自己申请。(不超过系统实际可用内存大小)堆是共享的,实际用多少分配多少(不用别人可以用)。
178+
179+
使用堆的情况:需要大量内存/不知道需要多大内存/需要跨函数使用
180+
181+
栈和堆是同一块物理内存的不同逻辑区域,可以调整栈和堆的大小比例。
182182

183+
```
184+
堆 = 公共仓库
185+
- 所有线程(工人)共享
186+
- 需要登记(加锁)才能拿东西
187+
- 容量大,但可能需要排队
183188
189+
栈 = 个人工具箱
190+
- 每个线程(工人)有自己的
191+
- 不需要跟别人抢
192+
- 空间小,但访问快
193+
```
194+
195+
| 特性 | 栈(Stack) | 堆(Heap) |
196+
|------|------------|-----------|
197+
| **共享性** | 每线程独立 | 所有线程共享 |
198+
| **空间分配** | 创建线程时预留 | 按需动态增长 |
199+
| **多线程开销** | 线程数 × 栈大小 | 所有线程共用一个 |
200+
| **线程安全** | 天然线程安全 | 需要同步机制 |
201+
| **访问速度** | 快(无竞争) | 较慢(可能竞争) |
202+
| **适用场景** | 临时变量、函数调用 | 共享数据、大对象 |
203+
:::
184204

185205
### 数组和函数
186206

187-
- 数组可以作为函数的参数使用,数组用作函数参数有两种形式:
188-
- 一种是把数组元素作为实参使用
189-
- 一种是把数组名作为函数的形参和实参使用
207+
数组可以作为函数的参数使用,数组用作函数参数有两种形式:
208+
- 一种是把数组元素作为实参使用
209+
- 一种是把数组名作为函数的形参和实参使用
190210

191211

192212
- 数组的元素作为函数实参,与同类型的简单变量作为实参一样,如果是基本数据类型, 那么形参的改变不影响实参
@@ -229,7 +249,6 @@ int main(int argc, const char * argv[])
229249
}
230250
```
231251

232-
---
233252

234253
### 数组名作函数参数的注意点
235254

@@ -279,10 +298,6 @@ void printArray(int array[])
279298
int a[2][3] = { {80,75,92}, {61,65,71}};
280299
```
281300

282-
- 可以看作由一维数组 a[0]和一维数组 a[1]组成,这两个一维数组都包含了 3 个 int 类型的元素
283-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/c716d53c6b228ea211a524645a5d13a5.png)
284-
285-
286301
- 格式:
287302

288303
* 数据类型 数组名[一维数组的个数][一维数组的元素个数]
@@ -353,9 +368,7 @@ int a[2][3]={[1][2]=10};int a[2][3]={[1]={1,2,3}}
353368
354369
### 二维数组的应用场景
355370
356-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/f351a6ed231c8a1a5e6379da6816fd1c.png)
357-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/dd8a18bdb49031d24c98bc311e80ab78.png)
358-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/dee64b6cb0f5c043402880d0062d2393.png)
371+
象棋、围棋的棋子的表示。网格地图的数据表示。
359372
360373
### 二维数组的遍历和存储
361374
@@ -392,11 +405,10 @@ int a[2][3]={[1][2]=10};int a[2][3]={[1]={1,2,3}}
392405
393406
> 注意: 必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量
394407
395-
---
396408
397409
### 二维数组的存储
398410
399-
- 和以为数组一样
411+
- 和一维数组一样
400412
401413
* 给数组分配存储空间从内存地址大开始分配
402414
* 给数组元素分配空间, 从所占用内存地址小的开始分配
@@ -419,7 +431,15 @@ int main()
419431
}
420432
```
421433

422-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/b3da2217fbaf93e346a390a47cad9a50.png)
434+
|二维数组变量名|内部一维数组|元素|地址|内容|
435+
|---|---|---|---|---|
436+
|cs|cs[1]|cs[1][2]||f|
437+
|cs|cs[1]|cs[1][1]|...|e|
438+
|cs|cs[1]|cs[1][0]|...|d|
439+
|cs|cs[0]|cs[0][2]|...|c|
440+
|cs|cs[0]|cs[0][1]|...|b|
441+
|cs|cs[0]|cs[0][0]||a|
442+
423443

424444
### 二维数组与函数
425445

@@ -534,8 +554,7 @@ void test(char cs[2][3])
534554

535555
- 字符串是位于双引号中的字符序列
536556

537-
* 在内存中以“\0”结束,所占字节比实际多一个
538-
![](https://images.weserv.nl/?url=https://img-blog.csdnimg.cn/img_convert/e0f0831ff1b110569a7e34440ab62e9e.png)
557+
* 在内存中以“\0”结束,所占字节比实际多一个例如:"Hello"在内存中存储为:"Hello\0"。
539558

540559
### 字符串的初始化
541560

0 commit comments

Comments
 (0)