doc: update c.md document (#913)
This commit is contained in:
parent
d7df8bc6fe
commit
e7b8958368
613
docs/c.md
613
docs/c.md
@ -7,7 +7,6 @@ C 备忘清单
|
||||
----
|
||||
|
||||
### hello.c
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
@ -35,40 +34,51 @@ $ ./hello
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```c
|
||||
int myNum = 15;
|
||||
int myNum = 15; // 定义并初始化变量 myNum
|
||||
int myNum2; // 声明变量 myNum2
|
||||
myNum2 = 15; // 初始化变量 myNum2
|
||||
|
||||
int myNum2; // 声明变量 myNum2
|
||||
// 变量声明后第一次赋值我们称为初始化
|
||||
// 如果 初始化 和 赋值 在同一行
|
||||
// 那么我们可以直接称为 定义变量 myNum2
|
||||
myNum2 = 15;
|
||||
int myNum3 = 15; // 定义并初始化变量 myNum3
|
||||
myNum3 = 10; // 重新赋值 myNum3
|
||||
```
|
||||
|
||||
int myNum3 = 15; // myNum3 值为 15
|
||||
myNum3 = 10; // 现在 myNum3 值为 10
|
||||
定义不同类型的变量
|
||||
|
||||
float myFloatNum = 5.99; // 浮点数
|
||||
char myLetter = 'D'; // 字符
|
||||
```c
|
||||
// 定义并初始化浮点数变量
|
||||
float myFloatNum = 5.99;
|
||||
// 定义并初始化字符变量
|
||||
char myLetter = 'D';
|
||||
```
|
||||
|
||||
int x = 5;
|
||||
int y = 6;
|
||||
int sum = x + y; // 添加变量相加
|
||||
// 声明多个变量
|
||||
变量相加
|
||||
|
||||
```c
|
||||
int x = 5, y = 6;
|
||||
int sum = x + y; // 变量相加
|
||||
```
|
||||
|
||||
声明并初始化多个变量
|
||||
|
||||
```c
|
||||
int x = 5, y = 6, z = 50;
|
||||
int a, b, c = 10;
|
||||
```
|
||||
|
||||
//仅声明变量不初始化
|
||||
仅声明变量不初始化
|
||||
|
||||
```c
|
||||
int result;
|
||||
// 如果未初始化,变量的值是未定义的,使用它会导致错误的结果。
|
||||
// 此时,变量的值是随机的,因此在使用该变量之前必须进行初始化。
|
||||
result = result + 10; // 错误:未初始化的变量 result 会导致不可预测的结果
|
||||
|
||||
// 部分编译器会输出 Warning,警告未初始化的变量可能导致未定义行为。
|
||||
// 未初始化的变量 result 会导致不可预测的结果
|
||||
|
||||
result = result + 10; // 错误:未初始化的变量
|
||||
// 部分编译器会警告未初始化的变量可能导致未定义行为
|
||||
```
|
||||
|
||||
### 常量 Constants
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
常量在 C 语言中我们一般理解为不能被改变的值,活用常量与符号常量,可以使代码更加清晰和安全
|
||||
常量是不能被改变的值,使用常量可以使代码更清晰和安全。
|
||||
|
||||
```c
|
||||
const int minutesPerHour = 60;
|
||||
@ -81,37 +91,53 @@ const float PI = 3.14;
|
||||
const int BIRTHYEAR = 1980;
|
||||
```
|
||||
|
||||
说明与补充:
|
||||
1. **常量命名规范**:常量通常使用全大写字母,多个单词之间用下划线分隔(例如 BIRTHYEAR、MAX_LENGTH)。
|
||||
#### **命名规范**
|
||||
<!--rehype:style=text-align: left;-->
|
||||
|
||||
2. **`#define` 与 `const`**:
|
||||
- **`#define`**:宏常量通常在预处理阶段进行替换,不进行类型检查;
|
||||
- **`const`**:类型安全的常量,编译器可以检查类型,一般更推荐使用 `const`
|
||||
常量通常使用全大写字母,单词间用下划线分隔(如 BIRTHYEAR、MAX_LENGTH)。
|
||||
|
||||
3. **数组大小**:可以使用 `const` 来定义数组的常量大小,这样编译器会将其作为编译时常量处理
|
||||
#### **数组大小**
|
||||
<!--rehype:style=text-align: left;-->
|
||||
|
||||
使用 `const` 定义数组大小,编译器将其作为编译时常量处理。
|
||||
|
||||
#### **`#define` 与 `const`**
|
||||
<!--rehype:style=text-align: left;-->
|
||||
|
||||
- `#define`:宏常量在预处理阶段替换,不进行类型检查
|
||||
- `const`:类型安全的常量,编译器可检查类型,推荐使用
|
||||
|
||||
#### **注意事项**
|
||||
|
||||
- `const` 常量在定义时必须初始化,否则会导致编译错误。
|
||||
- `const` 常量的值不能被修改,任何尝试修改 `const` 常量的操作都会导致编译错误。
|
||||
- 使用 `const` 常量可以提高代码的可读性和可维护性,避免魔法数字的使用。
|
||||
|
||||
### 注释
|
||||
|
||||
```c
|
||||
// 这是一个注释
|
||||
printf("Hello World!"); // 这是一个注释
|
||||
// 这是一个单行注释
|
||||
printf("Hello World!"); // 行内注释
|
||||
|
||||
/*
|
||||
多行注释:用于注释跨多行的内容
|
||||
上面的代码将打印出 Hello World! 到屏幕上
|
||||
多行注释:
|
||||
用于注释跨多行的内容
|
||||
注意:多行注释不能嵌套,否则会导致编译错误
|
||||
*/
|
||||
```
|
||||
**注意**:
|
||||
单行注释`//`可以嵌套,`////////这种注释也是对的`
|
||||
但行内注释应避免过长,以免影响代码可读性
|
||||
|
||||
多行注释不能嵌套,否则会导致编译错误(详见下文 [### Warning 和 Error](#warning-和-error) )
|
||||
**注意**:
|
||||
|
||||
- 单行注释 `//` 可以嵌套,如 `/////`。
|
||||
- 行内注释应避免过长,以免影响代码可读性。
|
||||
- 多行注释不能嵌套,否则会导致编译错误。
|
||||
|
||||
```c
|
||||
/* 这是一个多行注释的开始
|
||||
/* 这是嵌套的多行注释,C语言不支持 */
|
||||
/* 嵌套的多行注释,C语言不支持 */
|
||||
*/
|
||||
```
|
||||
<!--rehype:style=background:#ff000030;-->
|
||||
|
||||
### 打印文本
|
||||
|
||||
@ -126,21 +152,34 @@ printf("Value = %f", f);
|
||||
short a = 0b1010110; // 2 进制数字
|
||||
int b = 02713; // 8 进制数字
|
||||
long c = 0X1DAB83; // 16 进制数字
|
||||
//变量a和c分别为short和long型,所以输出必须加上对应的修饰符h和l
|
||||
```
|
||||
|
||||
// 以 8 进制形式输出
|
||||
变量a和c分别为 `short` 和 `long` 型,所以输出必须加上对应的修饰符 `h` 和 `l`
|
||||
|
||||
#### 以 8 进制形式输出
|
||||
|
||||
```c
|
||||
printf("a=%ho, b=%o, c=%lo\n", a, b, c);
|
||||
// 输出 => a=126, b=2713, c=7325603
|
||||
```
|
||||
|
||||
// 以 10 进制形式输出
|
||||
#### 以 10 进制形式输出
|
||||
|
||||
```c
|
||||
printf("a=%hd, b=%d, c=%ld\n", a, b, c);
|
||||
// 输出 => a=86, b=1483, c=1944451
|
||||
```
|
||||
|
||||
// 以 16 进制形式输出(字母小写)
|
||||
#### 以 16 进制形式输出(字母小写)
|
||||
|
||||
```c
|
||||
printf("a=%hx, b=%x, c=%lx\n", a, b, c);
|
||||
// 输出 => a=56, b=5cb, c=1dab83
|
||||
```
|
||||
|
||||
// 以 16 进制形式输出(字母大写)
|
||||
#### 以 16 进制形式输出(字母大写)
|
||||
|
||||
```c
|
||||
printf("a=%hX, b=%X, c=%lX\n", a, b, c);
|
||||
// 输出 => a=56, b=5CB, c=1DAB83
|
||||
```
|
||||
@ -169,73 +208,75 @@ printf("%-9d %-9d %-9d\n", d1, d2, d3);
|
||||
34 0 23
|
||||
```
|
||||
|
||||
`%-9d` 中,`d` 表示以 `10` 进制输出,`9` 表示最少占 `9` 个字符的宽度,宽度不足以空格补齐,`-` 表示左对齐,如果不使用左对齐则默认右对齐
|
||||
解释:`%-9d`:`d` 表示十进制输出,`9` 表示最少占 9 个字符宽度,`-` 表示左对齐,不使用 `-` 则默认右对齐。
|
||||
|
||||
对于整型数据:
|
||||
|
||||
对于整型数据,假设:
|
||||
```c
|
||||
int a = 12345;
|
||||
printf(“%md”,a);
|
||||
printf("%md", a);
|
||||
```
|
||||
1. 若 m <= 实际数据的宽度,则按实际情况输出
|
||||
2. 若 m > 实际数据的宽度,则在实际数据的左边用空格补齐
|
||||
3. `printf(“%0md”,a);` 则实际的结果不够 m 位的在数据的左边用0补齐
|
||||
|
||||
对于浮点型数据,**数据的宽度=整数部分的位数+小数点+小数部分的宽度**
|
||||
假设:
|
||||
- 若 `m <=` 实际数据宽度,则按实际情况输出。
|
||||
- 若 `m >` 实际数据宽度,则在左边用空格补齐。
|
||||
- `printf("%0md", a);` 则在左边用 `0` 补齐。
|
||||
|
||||
对于浮点型数据:
|
||||
|
||||
```c
|
||||
float a = 1.2345;
|
||||
printf(“%m.nf”,a); //m --整个数据的宽度,n--小数位数
|
||||
printf("%m.nf", a);
|
||||
// m -- 整个数据宽度,n -- 小数位数
|
||||
```
|
||||
1. 实际小数位数>n,截去小数右边多余的小数,截去的第一位要注意四舍五入
|
||||
2. 实际小数位数< n,在小数的最后补0
|
||||
3. 若m省略则写作%.n ,整数部分按照实际输出,小数部分按照以上两个规则进行
|
||||
4. m < n+1,自动突破宽度为m的限制,按照实际数据进行输出
|
||||
5. m > n+1,整个数据的最左边补空格
|
||||
|
||||
- 实际小数位数 `> n`,截去多余小数,注意四舍五入。
|
||||
- 实际小数位数 `< n`,在小数最后补 `0`。
|
||||
- 若 `m` 省略则写作 `%.n`,整数部分按实际输出,小数部分按以上规则。
|
||||
- 若 `m < n+1`,自动突破宽度限制,按实际数据输出。
|
||||
- 若 `m > n+1`,左边补空格。
|
||||
|
||||
### 字符串 Strings
|
||||
在C语言中,字符串是以 `\0` 结尾的字符数组,而不是一种单独的数据类型
|
||||
可以通过字符数组来表示字符串
|
||||
### 字符串 (Strings)
|
||||
|
||||
在 C 语言中,字符串是以 `\0` 结尾的字符数组,而不是一种单独的数据类型。可以通过字符数组来表示字符串。
|
||||
|
||||
#### 定义并打印字符串
|
||||
|
||||
定义并打印字符串
|
||||
```c
|
||||
char greetings[] = "Hello World!";
|
||||
printf("%s", greetings);
|
||||
```
|
||||
|
||||
访问字符串中的字符
|
||||
#### 访问字符串中的字符
|
||||
|
||||
```c
|
||||
char greetings[] = "Hello World!";
|
||||
printf("%c", greetings[0]);
|
||||
//这里我们访问字符串 greetings 的第一个字符'H'
|
||||
```
|
||||
|
||||
修改字符串中的字符
|
||||
访问字符串 `greetings` 的第一个字符 `H`
|
||||
|
||||
#### 修改字符串中的字符
|
||||
|
||||
```c
|
||||
char greetings[] = "Hello World!";
|
||||
greetings[0] = 'J'; //// 修改第一个字符为 'J'
|
||||
greetings[0] = 'J'; // 修改第一个字符为 'J'
|
||||
|
||||
printf("%s", greetings);
|
||||
// 输出 "Jello World!"
|
||||
```
|
||||
|
||||
另一种创建字符串的方法
|
||||
#### 另一种创建字符串的方法
|
||||
|
||||
```c
|
||||
char greetings[] = {'H','e','l','l','\0'};
|
||||
|
||||
printf("%s", greetings);
|
||||
// 输出 "Hell!"
|
||||
// 输出 "Hell"
|
||||
```
|
||||
|
||||
C语言中**没有**`String`类型,字符串是由字符数组(Array)`char[]`来表示的,且必须以 \0 结尾以标识字符串的结束
|
||||
|
||||
**注意**:C 语言中没有 `String` 类型,字符串是由字符数组 `char[]` 表示的,且必须以 `\0` 结尾以标识字符串的结束。
|
||||
|
||||
### 条件判断
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```c
|
||||
int time = 20;
|
||||
@ -245,6 +286,7 @@ if (time < 18) {
|
||||
printf("晚上好!");
|
||||
}
|
||||
// 输出 -> "晚上好!"
|
||||
|
||||
int time = 22;
|
||||
if (time < 10) {
|
||||
printf("早上好!");
|
||||
@ -265,25 +307,40 @@ if (time > 8) {
|
||||
// 输出 -> "中午好!"
|
||||
```
|
||||
|
||||
#### 说明
|
||||
|
||||
- `if` 语句用于根据条件执行代码块。
|
||||
- `else` 语句在 `if` 条件不满足时执行。
|
||||
- `else if` 语句用于检查多个条件。
|
||||
- 可以嵌套 `if` 语句以检查多个条件。
|
||||
|
||||
### 三元运算符
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
三元运算符(? :)是一种简洁的条件判断方式,常用于根据条件选择表达式的值,由三个部分组成:
|
||||
- 一个条件表达式
|
||||
|
||||
三元运算符(`? :`)是一种简洁的条件判断方式,用于根据条件选择表达式的值。由三个部分组成:
|
||||
|
||||
- 条件表达式
|
||||
- 条件为真时的结果
|
||||
- 条件为假时的结果
|
||||
基本语法:`(condition) ? expression1 : expression2;`
|
||||
如果`condition`为真,则返回`expression1`否则返回`expression2`。
|
||||
|
||||
基本语法:`(条件) ? 表达式1 : 表达式2;`
|
||||
如果 `条件` 为真,则返回 `表达式1`,否则返回 `表达式2`。
|
||||
|
||||
#### 示例
|
||||
|
||||
```c
|
||||
int time = 20;
|
||||
(time < 18) ? printf("再会!") : printf("晚上好!");
|
||||
(time < 18) ? printf("再会!")
|
||||
: printf("晚上好!");
|
||||
// 输出 -> "晚上好!"
|
||||
```
|
||||
|
||||
三元运算符可以嵌套使用,但嵌套层级太多会导致代码可读性下降,不建议在实际场景使用
|
||||
嵌套使用示例(不建议过多嵌套):
|
||||
|
||||
```c
|
||||
int time = 22;
|
||||
printf((time < 10) ? "早上好!" : (time < 20) ? "再会!" : "晚上好!");
|
||||
printf((time < 10) ? "早上好!"
|
||||
: (time < 20) ? "再会!"
|
||||
: "晚上好!");
|
||||
// 输出 -> "晚上好!"
|
||||
```
|
||||
|
||||
@ -295,30 +352,34 @@ int day = 4;
|
||||
switch (day) {
|
||||
case 3: printf("周三"); break;
|
||||
case 4: printf("周四"); break;
|
||||
default:
|
||||
printf("期待周末");
|
||||
default: printf("期待周末");
|
||||
}
|
||||
// 输出 -> "周四" (day 4)
|
||||
/* 解释:
|
||||
switch 语句会根据表达式 day 的值来跳转到匹配的 case 标签
|
||||
匹配到 case 4 时,会执行相应的代码并通过 break 跳出 switch 语句
|
||||
如果没有匹配到任何 case,则会执行 default 语句(如果存在)
|
||||
*/
|
||||
// 输出 -> "周四"
|
||||
```
|
||||
注意:
|
||||
1. switch 后面括号中的表达式可以是整型、字符型和枚举型
|
||||
2. 在`case`后的各常量表达式的值不能相同
|
||||
3. 在`case`后,允许有多个语句,可以不用{ }括起来,而整个 switc h结构一定要有一对{}
|
||||
4. 各`case`和`default`语句的先后顺序可以改变,不影响程序执行结果
|
||||
5. `break`语句用于结束 switch,如果没有`break`,程序会穿透到下一个`case`继续执行,例如
|
||||
|
||||
#### 说明
|
||||
|
||||
- `switch` 语句根据表达式的值跳转到匹配的 `case` 标签。
|
||||
- 匹配到 `case` 后执行相应代码,并通过 `break` 跳出 `switch`。
|
||||
- 如果没有匹配到任何 `case`,则执行 `default` 语句(如果存在)。
|
||||
|
||||
#### 注意事项
|
||||
|
||||
- `switch` 表达式可以是整型、字符型和枚举型。
|
||||
- `case` 后的常量表达式值不能相同。
|
||||
- `case` 后可以有多个语句,不需要 `{ }` 括起来。
|
||||
- `case` 和 `default` 语句的顺序不影响程序执行结果。
|
||||
- `break` 语句用于结束 `switch`,如果没有 `break`,程序会继续执行下一个 `case`。
|
||||
|
||||
#### 示例
|
||||
|
||||
```c
|
||||
int day = 3;
|
||||
|
||||
switch (day) {
|
||||
case 3: printf("周三");
|
||||
case 4: printf("周四"); break;
|
||||
default:
|
||||
printf("期待周末");
|
||||
default: printf("期待周末");
|
||||
}
|
||||
// 输出 -> "周三周四"
|
||||
```
|
||||
@ -332,14 +393,53 @@ while (i < 5) {
|
||||
printf("%d\n", i);
|
||||
i++;
|
||||
}
|
||||
/*解释:
|
||||
在 while 循环中,首先检查条件 i < 5 是否为真
|
||||
如果为真,程序进入循环体,执行打印操作并增加 i 的值
|
||||
循环会继续进行,直到 i 达到 5,此时条件 i < 5 不再为真,循环结束
|
||||
*/
|
||||
// 输出 -> 0 1 2 3 4
|
||||
```
|
||||
|
||||
**注意**:不要忘记在循环体内修改循环条件中的变量(如 i++),否则循环将永远执行下去,成为“死循环”
|
||||
#### 解释
|
||||
|
||||
- `while` 循环首先检查条件 `i < 5` 是否为真。
|
||||
- 如果为真,程序进入循环体,执行打印操作并增加 `i` 的值。
|
||||
- 循环会继续进行,直到 `i` 达到 5,此时条件 `i < 5` 不再为真,循环结束。
|
||||
|
||||
#### 打印 1 到 10 的数字
|
||||
|
||||
```c
|
||||
int i = 1;
|
||||
|
||||
while (i <= 10) {
|
||||
printf("%d\n", i);
|
||||
i++;
|
||||
}
|
||||
// 输出 -> 1 2 3 4 5 6 7 8 9 10
|
||||
```
|
||||
|
||||
#### 打印偶数
|
||||
|
||||
```c
|
||||
int i = 0;
|
||||
|
||||
while (i <= 10) {
|
||||
if (i % 2 == 0) {
|
||||
printf("%d\n", i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// 输出 -> 0 2 4 6 8 10
|
||||
```
|
||||
|
||||
#### 无限循环(需手动终止)
|
||||
|
||||
```c
|
||||
int i = 0;
|
||||
|
||||
while (1) {
|
||||
printf("无限循环\n");
|
||||
i++;
|
||||
if (i == 5) break; // 添加条件以退出循环
|
||||
}
|
||||
// 输出 -> 无限循环 (打印 5 次)
|
||||
```
|
||||
|
||||
### Do/While 循环
|
||||
|
||||
@ -350,33 +450,55 @@ do {
|
||||
printf("%d\n", i);
|
||||
i++;
|
||||
} while (i < 5);
|
||||
/*解释:
|
||||
在 do/while 循环中,循环体至少执行一次,因为条件检查是在循环体执行之后进行的
|
||||
首先执行 do 中的代码,然后检查条件 i < 5 是否为真
|
||||
如果为真,继续执行循环;如果为假,则退出循环
|
||||
/*
|
||||
// 输出 -> 0 1 2 3 4
|
||||
```
|
||||
**注意**:与`while`循环不同,`do/while`循环会确保至少执行一次循环体,即使条件一开始就为假
|
||||
例如,以下代码虽然条件`i < 5`初始时为假,但仍然会执行一次:
|
||||
```C
|
||||
|
||||
#### 解释
|
||||
|
||||
- `do/while` 循环至少执行一次循环体,因为条件检查在循环体执行之后进行。
|
||||
- 首先执行 `do` 中的代码,然后检查条件 `i < 5` 是否为真。
|
||||
- 如果为真,继续执行循环;如果为假,则退出循环。
|
||||
|
||||
#### 打印从 5 开始的数字,直到条件不满足
|
||||
|
||||
```c
|
||||
int i = 5;
|
||||
|
||||
do {
|
||||
printf("%d\n", i); // 输出 5
|
||||
i++;
|
||||
} while (i < 5);
|
||||
// 输出 -> 5
|
||||
```
|
||||
|
||||
#### 计算 1 到 10 的和
|
||||
|
||||
```c
|
||||
int i = 1;
|
||||
int sum = 0;
|
||||
|
||||
do {
|
||||
sum += i;
|
||||
i++;
|
||||
} while (i <= 10);
|
||||
|
||||
printf("Sum: %d\n", sum);
|
||||
// 输出 -> Sum: 55
|
||||
```
|
||||
|
||||
### For 循环
|
||||
语法:
|
||||
```C
|
||||
for(表达式 1;表达式 2;表达式 3){
|
||||
|
||||
```c
|
||||
for (表达式1; 表达式2; 表达式3) {
|
||||
循环体语句;
|
||||
}
|
||||
```
|
||||
表达式 1:设置初始条件,只执行一次,为 0 个或多个变量设置初值
|
||||
表达式 2:是循环条件表达式,用来判定是否继续循环。在每次执行循环体之前要先执行表达式 2,然后再决定是否继续执行循环
|
||||
表达式 3:作为循环的调整,比如是循环体变量增值,它是执行循环体语句之后再执行
|
||||
|
||||
- 表达式1:设置初始条件,只执行一次。
|
||||
- 表达式2:循环条件表达式,每次循环前检查。
|
||||
- 表达式3:循环体执行后的调整操作。
|
||||
|
||||
示例:
|
||||
|
||||
```c
|
||||
int i;
|
||||
@ -384,40 +506,28 @@ int i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
printf("%d\n", i);
|
||||
}
|
||||
/* 输出:
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
*/
|
||||
// 输出 -> 0 1 2 3 4
|
||||
```
|
||||
|
||||
**注意**:
|
||||
1. for 语句的三个表达式不是必须的
|
||||
2. 当条件表达式(表达式 2)的值为假(为 0)时 for 循环语句就结束
|
||||
3. 可以在循环体内执行`break`,`continue`,`goto`语句
|
||||
4. 若表达式 2 是空的,表明表达式 2 的值一直是真,即死循环
|
||||
如:`for(;;) //死循环语句 相当于while(1)`
|
||||
#### 注意事项
|
||||
|
||||
**变体**:
|
||||
- `for(i = m; i < n; i++)`会从 i = m 开始到 i = n-1,循环 n - m 次
|
||||
- `for(i = m; i <= n; i++)`会从 i = m 到 i = n,循环 n - m + 1 次
|
||||
- `for` 语句的三个表达式不是必须的。
|
||||
- 当条件表达式(表达式2)为假时,`for` 循环结束。
|
||||
- 可以在循环体内使用 `break`、`continue`、`goto` 语句。
|
||||
- 如果表达式2为空,则表示无限循环,如 `for(;;)` 相当于 `while(1)`。
|
||||
|
||||
#### 变体
|
||||
|
||||
- `for (i = m; i < n; i++)` 从 `i = m` 开始到 `i = n-1`,循环 `n - m` 次。
|
||||
- `for (i = m; i <= n; i++)` 从 `i = m` 到 `i = n`,循环 `n - m + 1` 次。
|
||||
|
||||
### 跳出循环 (Break/Continue/Goto)
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
|
||||
#### `break` 语句
|
||||
|
||||
### 跳出循环(中断语句) Break/Continue/Goto
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
`break`语句:跳出本层循环,执行循环后的语句
|
||||
`continue`语句:跳出本次循环,执行下一次循环
|
||||
`goto`语句:跳出到指定的标号位
|
||||
跳出当前循环或 `switch` 语句,执行后续代码。
|
||||
|
||||
**1.`break`语句**:
|
||||
|
||||
`break`用于跳出当前的循环或`switch`语句,直接跳到循环或`switch`语句之后的下一条语句
|
||||
通常用于在特定条件下提前结束循环
|
||||
```c
|
||||
int i;
|
||||
|
||||
@ -427,16 +537,13 @@ for (i = 0; i < 10; i++) {
|
||||
}
|
||||
printf("%d\n", i);
|
||||
}
|
||||
//输出:
|
||||
//0 1 2 3 4(换行符使用空格代替)
|
||||
// 输出 -> 0 1 2 3
|
||||
```
|
||||
|
||||
当`i`等于 4 时,`break`语句使得循环提前结束,因此没有打印出 4 及之后的值
|
||||
#### `continue` 语句
|
||||
|
||||
**2.`continue`语句**:
|
||||
跳过当前循环的剩余语句,直接进入下一次循环。
|
||||
|
||||
`continue`用于跳过当前循环中的剩余语句(在for循环中相当于直接执行表达式3),直接进入下一次循环的条件判断阶段
|
||||
通常用于跳过某些特定的循环迭代
|
||||
```c
|
||||
int i;
|
||||
|
||||
@ -446,17 +553,14 @@ for (i = 0; i < 10; i++) {
|
||||
}
|
||||
printf("%d\n", i);
|
||||
}
|
||||
//输出:
|
||||
//0 1 2 3 5 6 7 8 9(换行符使用空格代替)
|
||||
// 输出 -> 0 1 2 3 5 6 7 8 9
|
||||
```
|
||||
|
||||
当`i`等于 4 时,`continue`会跳过打印语句,因此 4 被跳过,不会输出
|
||||
#### `goto` 语句
|
||||
|
||||
**3.`goto`语句**:
|
||||
无条件跳转到指定标签位置。
|
||||
|
||||
`goto`用于无条件跳转到程序中的指定标签位置
|
||||
|
||||
```C
|
||||
```c
|
||||
int i = 0;
|
||||
|
||||
while (i < 10) {
|
||||
@ -469,56 +573,20 @@ while (i < 10) {
|
||||
|
||||
skip:
|
||||
printf("Exited the loop at i = %d\n", i);
|
||||
/* 输出:
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
Exited the loop at i = 4
|
||||
*/
|
||||
// 输出 -> 0 1 2 3 Exited the loop at i = 4
|
||||
```
|
||||
|
||||
`goto skip`语句将程序的控制流跳转到标签`skip`处,导致循环在`i = 4`时直接结束,并输出`Exited the loop at i = 4`
|
||||
#### 注意事项
|
||||
|
||||
**注意**:
|
||||
1. `label标签`必须是在当前函数内定义的标签。标签的命名规则与变量的命名规则相同,但标签不能与C语言的关键字冲突
|
||||
2. `goto`语句通常用于跳转到同一函数内的某个位置,但也可以跳转到同一文件中的其他函数内的标签(不推荐)
|
||||
3. goto语句应慎用,因为过多或滥用goto语句可能会导致代码逻辑混乱、难以维护和阅读。通常情况下,可以使用循环或条件语句等结构化的控制流语句来代替goto语句
|
||||
- 标签必须在当前函数内定义,命名规则与变量相同。
|
||||
- `goto` 语句应慎用,避免代码逻辑混乱,通常使用循环或条件语句代替。
|
||||
|
||||
### 数组 Arrays
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
#### 设置数组大小
|
||||
|
||||
```c
|
||||
int myNumbers[] = {25, 50, 75, 100};
|
||||
printf("%d", myNumbers[0]);
|
||||
// 输出 25
|
||||
```
|
||||
|
||||
更改数组元素
|
||||
|
||||
```c
|
||||
int myNumbers[] = {25, 50, 75, 100};
|
||||
myNumbers[0] = 33;
|
||||
|
||||
printf("%d", myNumbers[0]);
|
||||
```
|
||||
|
||||
循环遍历数组
|
||||
|
||||
```c
|
||||
int myNumbers[] = {25, 50, 75, 100};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("%d\n", myNumbers[i]);
|
||||
}
|
||||
```
|
||||
|
||||
设置数组大小
|
||||
|
||||
```c
|
||||
// 声明一个由四个整数组成的数组:
|
||||
// 声明一个由四个整数组成的数组
|
||||
int myNumbers[4];
|
||||
|
||||
// 添加元素
|
||||
myNumbers[0] = 25;
|
||||
myNumbers[1] = 50;
|
||||
@ -566,6 +634,35 @@ switch(day){
|
||||
}
|
||||
```
|
||||
|
||||
### 数组 Arrays
|
||||
|
||||
#### 定义和访问数组元素
|
||||
|
||||
```c
|
||||
int myNumbers[] = {25, 50, 75, 100};
|
||||
printf("%d", myNumbers[0]); // 输出 25
|
||||
```
|
||||
|
||||
#### 更改数组元素
|
||||
|
||||
```c
|
||||
int myNumbers[] = {25, 50, 75, 100};
|
||||
myNumbers[0] = 33;
|
||||
printf("%d", myNumbers[0]); // 输出 33
|
||||
```
|
||||
|
||||
#### 循环遍历数组
|
||||
|
||||
```c
|
||||
int myNumbers[] = {25, 50, 75, 100};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("%d\n", myNumbers[i]);
|
||||
}
|
||||
// 输出 -> 25 50 75 100
|
||||
```
|
||||
|
||||
### 用户输入
|
||||
|
||||
```c
|
||||
@ -597,39 +694,27 @@ printf("Hello %s.", firstName);
|
||||
|
||||
### 内存地址
|
||||
|
||||
创建变量时,会为该变量分配一个内存地址
|
||||
创建变量时,会为该变量分配一个内存地址。
|
||||
|
||||
```c
|
||||
int myAge = 43;
|
||||
|
||||
printf("%p", &myAge);
|
||||
// 输出:0x7ffe5367e044
|
||||
// 输出 myAge 的内存地址,例如:0x7ffe5367e044
|
||||
```
|
||||
|
||||
要访问它,请使用引用运算符 (`&`)
|
||||
要访问变量的内存地址,请使用引用运算符 (`&`)。
|
||||
|
||||
### 创建指针
|
||||
|
||||
```c
|
||||
int myAge = 43; // 一个 int 变量
|
||||
printf("%d", myAge); // 输出 myAge(43)的值
|
||||
|
||||
// 输出 myAge 的内存地址(0x7ffe5367e044)
|
||||
printf("%p", &myAge);
|
||||
```
|
||||
|
||||
### 指针变量
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```c
|
||||
int myAge = 43; // 一个 int 变量
|
||||
int* ptr = &myAge; // 名为 ptr 的指针变量,用于存储 myAge 的地址
|
||||
int myAge = 43; // 一个 int 变量
|
||||
int *ptr = &myAge; // 创建指向 myAge 的指针
|
||||
|
||||
printf("%d\n", myAge); // 输出 myAge (43) 的值
|
||||
|
||||
printf("%p\n", &myAge); // 输出 myAge 的内存地址(0x7ffe5367e044)
|
||||
|
||||
printf("%p\n", ptr); // 用指针(0x7ffe5367e044)输出myAge的内存地址
|
||||
printf("%d\n", myAge); // 输出 myAge 的值 -> 43
|
||||
printf("%p\n", &myAge); // 输出 myAge 的内存地址,例如:0x7ffe5367e044
|
||||
printf("%p\n", ptr); // 输出指针 ptr 的值(即 myAge 的内存地址)
|
||||
printf("%d\n", *ptr); // 通过指针访问 myAge 的值 -> 43
|
||||
```
|
||||
|
||||
### 取消引用
|
||||
@ -645,6 +730,18 @@ printf("%p\n", ptr);
|
||||
printf("%d\n", *ptr);
|
||||
```
|
||||
|
||||
### 指针变量
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```c
|
||||
int myAge = 43; // 一个 int 变量
|
||||
int* ptr = &myAge; // 名为 ptr 的指针变量,用于存储 myAge 的地址
|
||||
|
||||
printf("%d\n", myAge); // 输出 myAge (43) 的值
|
||||
printf("%p\n", &myAge); // 输出 myAge 的内存地址(0x7ffe5367e044)
|
||||
printf("%p\n", ptr); // 用指针(0x7ffe5367e044)输出myAge的内存地址
|
||||
```
|
||||
|
||||
运算符
|
||||
---
|
||||
|
||||
@ -987,46 +1084,78 @@ int main(void) {
|
||||
### Warning 和 Error
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
在 C 语言中,警告(Warning)和错误(Error)是编译器用于标识代码潜在问题或阻止代码编译的两种机制
|
||||
在 C 语言中,警告(Warning)和错误(Error)是编译器用于标识代码潜在问题或阻止代码编译的机制。
|
||||
|
||||
#### 警告
|
||||
|
||||
**警告**:
|
||||
警告提示代码中可能存在的问题,但不会阻止代码编译。处理警告可以提升代码质量和可移植性。
|
||||
|
||||
**常见警告示例**:
|
||||
1. 未使用的变量
|
||||
`int x; printf("%d",x);`
|
||||
2. 类型隐式转换(可能导致数据丢失)
|
||||
`int x = 3.14; //浮点数被隐式转换`
|
||||
`int a = 2147483647 + 1; //可能溢出`
|
||||
3. 函数声明与定义不匹配
|
||||
#### **常见警告示例**
|
||||
|
||||
**错误**:
|
||||
警告提示代码中可能存在的问题,但不会阻止代码编译。处理警告可以提升代码质量和可移植性。
|
||||
未使用的变量
|
||||
|
||||
```c
|
||||
int x; printf("%d", x);
|
||||
```
|
||||
|
||||
类型隐式转换(可能导致数据丢失)
|
||||
|
||||
```c
|
||||
int x = 3.14; // 浮点数被隐式转换
|
||||
int a = 2147483647 + 1; // 可能溢出
|
||||
```
|
||||
|
||||
函数声明与定义不匹配
|
||||
|
||||
#### 错误
|
||||
|
||||
错误会阻止代码编译,必须修复才能继续编译。
|
||||
|
||||
**常见错误示例**:
|
||||
1. 语法错误(如缺少分号)
|
||||
`int x=1 `
|
||||
2. 函数定义冲突
|
||||
```C
|
||||
|
||||
语法错误(如缺少分号)
|
||||
|
||||
```c
|
||||
int x = 1
|
||||
```
|
||||
|
||||
函数定义冲突
|
||||
|
||||
```c
|
||||
void func(int);
|
||||
void func(double);
|
||||
```
|
||||
3. 函数或变量未定义
|
||||
`y = 10; printf("%d",y);`
|
||||
4. 头文件缺失或冲突
|
||||
`#include <unknown.h>`
|
||||
|
||||
**使用编译器指令控制警告和错误**:
|
||||
1. 抑制警告
|
||||
函数或变量未定义
|
||||
|
||||
```c
|
||||
y = 10; printf("%d", y);
|
||||
```
|
||||
|
||||
头文件缺失或冲突
|
||||
|
||||
```c
|
||||
#include <unknown.h>
|
||||
```
|
||||
|
||||
### 使用编译器指令控制警告和错误
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
#### 抑制警告
|
||||
|
||||
可以使用编译器选项来关闭特定的警告,例如在 GCC 中:
|
||||
```GCC
|
||||
|
||||
```sh
|
||||
gcc -w file.c # 禁用所有警告
|
||||
gcc -Wall file.c # 启用所有常见警告
|
||||
gcc -Werror file.c # 将警告视为错误
|
||||
```
|
||||
2. 使用 #pragma 控制警告
|
||||
在某些编译器中,可以使用`#pragma`指令启用或禁用警告
|
||||
```C
|
||||
|
||||
#### 使用 `#pragma` 控制警告
|
||||
|
||||
在某些编译器中,可以使用 `#pragma` 指令启用或禁用警告:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#pragma warning(disable : 4996) // 禁用警告(适用于 MSVC 编译器)
|
||||
|
||||
@ -1036,7 +1165,8 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
**总结**
|
||||
#### 总结
|
||||
|
||||
| 区别点 | Warning(警告) | Error(错误) |
|
||||
|------------------|----------------------------------------|----------------------------------------|
|
||||
| 严重程度 | 程序可继续编译,但可能存在隐患 | 编译无法完成,必须修复 |
|
||||
@ -1045,7 +1175,6 @@ int main() {
|
||||
| 修复必要性 | 可选择修复,但建议修复以避免潜在问题 | 必须修复才能继续编译 |
|
||||
| 编译器选项调整 | 可以忽略或转换为错误(如 `-Werror`) | 无法调整,必须修复 |
|
||||
|
||||
|
||||
函数
|
||||
----
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user