Skip to content

Commit

Permalink
doc: update c.md (#911)
Browse files Browse the repository at this point in the history
  • Loading branch information
ThanatosXingYu authored Dec 29, 2024
1 parent b3893d8 commit 6c82172
Showing 1 changed file with 147 additions and 5 deletions.
152 changes: 147 additions & 5 deletions docs/c.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,21 @@ int y = 6;
int sum = x + y; // 添加变量相加
// 声明多个变量
int x = 5, y = 6, z = 50;
int a, b, c = 10;

//仅声明变量不初始化
int result;
// 如果未初始化,变量的值是未定义的,使用它会导致错误的结果。
// 此时,变量的值是随机的,因此在使用该变量之前必须进行初始化。
result = result + 10; // 错误:未初始化的变量 result 会导致不可预测的结果

// 部分编译器会输出 Warning,警告未初始化的变量可能导致未定义行为。

```

### 常量 Constants

常量在 C 语言中我们一般理解为不能被改变的值,活用常量与符号常量
常量在 C 语言中我们一般理解为不能被改变的值,活用常量与符号常量,可以使代码更加清晰和安全

```c
const int minutesPerHour = 60;
Expand All @@ -71,13 +81,36 @@ const float PI = 3.14;
const int BIRTHYEAR = 1980;
```

说明与补充:
1. **常量命名规范**:常量通常使用全大写字母,多个单词之间用下划线分隔(例如 BIRTHYEAR、MAX_LENGTH)。

2. **`#define``const`**
- **`#define`**:宏常量通常在预处理阶段进行替换,不进行类型检查;
- **`const`**:类型安全的常量,编译器可以检查类型,一般更推荐使用 `const`

3. **数组大小**:可以使用 `const` 来定义数组的常量大小,这样编译器会将其作为编译时常量处理



### 注释

```c
// 这是一个注释
printf("Hello World!"); // 这是一个注释
/* 多行注释,上面的代码将打印出 Hello World!
到屏幕上,真是太棒了 */
/*
多行注释:用于注释跨多行的内容
上面的代码将打印出 Hello World! 到屏幕上
注意:多行注释不能嵌套,否则会导致编译错误
*/
```
**注意**:
单行注释`//`可以嵌套,`////////这种注释也是对的`
但行内注释应避免过长,以免影响代码可读性
多行注释不能嵌套,否则会导致编译错误(详见下文 [### Warning 和 Error](#warning-和-error) )
```c
/* 这是一个多行注释的开始
/* 这是嵌套的多行注释,C语言不支持 */
```

### 打印文本
Expand All @@ -93,8 +126,9 @@ printf("Value = %f", f);
short a = 0b1010110; // 2 进制数字
int b = 02713; // 8 进制数字
long c = 0X1DAB83; // 16 进制数字
//变量a和c分别为short和long型,所以输出必须加上对应的修饰符h和l

// 以 8 进制形似输出
// 以 8 进制形式输出
printf("a=%ho, b=%o, c=%lo\n", a, b, c);
// 输出 => a=126, b=2713, c=7325603

Expand All @@ -119,6 +153,7 @@ int b1=56720, b2=9999, b3=20098;
int c1=233, c2=205, c3=1;
int d1=34, d2=0, d3=23;
// %-9d: 十进制输出,最少宽度为9,左对齐
printf("%-9d %-9d %-9d\n", a1, a2, a3);
printf("%-9d %-9d %-9d\n", b1, b2, b3);
printf("%-9d %-9d %-9d\n", c1, c2, c3);
Expand All @@ -134,7 +169,29 @@ printf("%-9d %-9d %-9d\n", d1, d2, d3);
34 0 23
```

`%-9d` 中,`d` 表示以 `10` 进制输出,`9` 表示最少占 `9` 个字符的宽度,宽度不足以空格补齐,`-` 表示左对齐
`%-9d` 中,`d` 表示以 `10` 进制输出,`9` 表示最少占 `9` 个字符的宽度,宽度不足以空格补齐,`-` 表示左对齐,如果不使用左对齐则默认右对齐

对于整型数据,假设:
```c
int a = 12345;
printf(“%md”,a);
```
1. 若 m <= 实际数据的宽度,则按实际情况输出
2. 若 m > 实际数据的宽度,则在实际数据的左边用空格补齐
3. `printf(“%0md”,a);` 则实际的结果不够 m 位的在数据的左边用0补齐
对于浮点型数据,宽度=整数部分的位数+小数点+小数部分的宽度
假设:
```c
float a = 1.2345;
printf(“%m.nf”,a); //m --整个数据的宽度,n--小数位数
```
1. 实际小数位数>n,截去小数右边多余的小数,截去的第一位要注意四舍五入
2. 实际小数位数< n,在小数的最后补0
3. 若m省略则写作%.n ,整数部分按照实际输出,小数部分按照以上两个规则进行
4. m < n+1,自动突破宽度为m的限制,按照实际数据进行输出
5. m > n+1,整个数据的最左边补空格


### 字符串 Strings

Expand Down Expand Up @@ -191,14 +248,37 @@ if (time < 10) {
printf("晚上好!");
}
// 输出 -> "晚上好!"

int time = 10;
if (time > 8) {
//再嵌套一个if
if (time < 12) {
printf("中午好!")
}
}
// 输出 -> "中午好!"
```

### 三元运算符
<!--rehype:wrap-class=col-span-2-->
三元运算符(? :)是一种简洁的条件判断方式,常用于根据条件选择表达式的值,由三个部分组成:
- 一个条件表达式
- 条件为真时的结果
- 条件为假时的结果
基本语法:`(condition) ? expression1 : expression2;`
如果`condition`为真,则返回`expression1`否则返回`expression2`

```c
int time = 20;
(time < 18) ? printf("再会!") : printf("晚上好!");
// 输出 -> "晚上好!"
```

三元运算符可以嵌套使用,但嵌套层级太多会导致代码可读性下降,不建议在实际场景使用
```c
int time = 22;
printf((time < 10) ? "早上好!" : (time < 20) ? "再会!" : "晚上好!");
// 输出 -> "晚上好!"
```
### Switch
Expand Down Expand Up @@ -805,6 +885,68 @@ int main(void) {
}
```

### Warning 和 Error
<!--rehype:wrap-class=row-span-2-->

在 C 语言中,警告(Warning)和错误(Error)是编译器用于标识代码潜在问题或阻止代码编译的两种机制

**警告**:
警告提示代码中可能存在的问题,但不会阻止代码编译。处理警告可以提升代码质量和可移植性。

**常见警告示例**:
1. 未使用的变量
`int x; printf("%d",x);`
2. 类型隐式转换(可能导致数据丢失)
`int x = 3.14; //浮点数被隐式转换`
`int a = 2147483647 + 1; //可能溢出`
3. 函数声明与定义不匹配

**错误**:
警告提示代码中可能存在的问题,但不会阻止代码编译。处理警告可以提升代码质量和可移植性。

**常见错误示例**:
1. 语法错误(如缺少分号)
`int x=1 `
2. 函数定义冲突
```C
void func(int);
void func(double);
```
3. 函数或变量未定义
`y = 10; printf("%d",y);`
4. 头文件缺失或冲突
`#include <unknown.h>`
**使用编译器指令控制警告和错误**:
1. 抑制警告
可以使用编译器选项来关闭特定的警告,例如在 GCC 中:
```GCC
gcc -w file.c # 禁用所有警告
gcc -Wall file.c # 启用所有常见警告
gcc -Werror file.c # 将警告视为错误
```
2. 使用 #pragma 控制警告
在某些编译器中,可以使用`#pragma`指令启用或禁用警告
```C
#include <stdio.h>
#pragma warning(disable : 4996) // 禁用警告(适用于 MSVC 编译器)

int main() {
printf("Hello, world!");
return 0;
}
```

**总结**
| 区别点 | Warning(警告) | Error(错误) |
|------------------|----------------------------------------|----------------------------------------|
| 严重程度 | 程序可继续编译,但可能存在隐患 | 编译无法完成,必须修复 |
| 编译结果 | 生成可执行文件 | 无法生成可执行文件 |
| 触发原因 | 潜在问题,例如隐式转换或未使用的变量 | 语法或语义错误,例如语法错误或未定义变量 |
| 修复必要性 | 可选择修复,但建议修复以避免潜在问题 | 必须修复才能继续编译 |
| 编译器选项调整 | 可以忽略或转换为错误(如 `-Werror`| 无法调整,必须修复 |


函数
----

Expand Down

0 comments on commit 6c82172

Please sign in to comment.