🌈 style:
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [第一章 绪论](#第一章-绪论)
|
||||
- [第一节](#第一节)
|
||||
@@ -27,12 +28,6 @@
|
||||
- [进程](#进程)
|
||||
- [防止写越界,防止内存泄漏,谁打开谁关闭,谁申请谁释放](#防止写越界防止内存泄漏谁打开谁关闭谁申请谁释放)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 第一章 绪论
|
||||
|
||||
课程地址,[史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV18p4y167Md/?spm_id_from=333.999.0.0&vd_source=4e03f52e94cfa281cde032856b1f93a7)。
|
||||
@@ -49,8 +44,6 @@
|
||||
| 1967 | B语言 |
|
||||
| 1973 | C语言 |
|
||||
|
||||
|
||||
|
||||
### C语言特点
|
||||
|
||||
1. 基础性语言
|
||||
@@ -60,8 +53,6 @@
|
||||
5. 移植性好,执行效率高
|
||||
6. 允许直接对硬件操作
|
||||
|
||||
|
||||
|
||||
### C语言学习建议
|
||||
|
||||
1. 概念的正确性
|
||||
@@ -69,8 +60,6 @@
|
||||
3. 阅读优秀的程序段
|
||||
4. 大量练习,面试题
|
||||
|
||||
|
||||
|
||||
### 课程思路
|
||||
|
||||
1. 基础概念
|
||||
@@ -85,17 +74,13 @@
|
||||
10. 调试工具(gdb,make)
|
||||
11. 常用库函数
|
||||
|
||||
|
||||
|
||||
### 课程平台
|
||||
|
||||
* 老师:64位的`redhat6`,`vim`,`gcc4.4.6(make)`
|
||||
* 本人:`WSL-debian`,`vscode(remote ssh)`,`gcc12.2.0(make)`,`ohmyzsh(theme:eastwood)`
|
||||
- 老师:64位的`redhat6`,`vim`,`gcc4.4.6(make)`
|
||||
- 本人:`WSL-debian`,`vscode(remote ssh)`,`gcc12.2.0(make)`,`ohmyzsh(theme:eastwood)`
|
||||
|
||||
我的`gcc`版本比较新,所以很多提示比较完善,老师这个课程是很早的课,那个时候的gcc提示没有现在厉害,所以还是要结合老师的视频的思路,在当时提示不完善的时候是如何手撕代码分析出来的。
|
||||
|
||||
|
||||
|
||||
## 第二节
|
||||
|
||||
### 神一般的`Hello world!`
|
||||
@@ -122,8 +107,6 @@ int main(void)
|
||||
|
||||
用哪种`main`得看编译器环境,目前在`linux`的`gcc`下,`int main(void);`常用,需要传参用`int main(int argc, char **argv);`。
|
||||
|
||||
|
||||
|
||||
### 源文件到可执行文件
|
||||
|
||||
#### gcc
|
||||
@@ -147,8 +130,6 @@ gcc hello.c # 得到a.out可执行文件
|
||||
gcc hello.c -o myhello # 得到myhello可执行文件
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### make
|
||||
|
||||
```bash
|
||||
@@ -159,14 +140,10 @@ $ ls
|
||||
hello hello.c
|
||||
```
|
||||
|
||||
|
||||
|
||||
### vim
|
||||
|
||||
老师对于常用的`.vimrc`做了一些介绍,笔者建议`vscode`的`remote-ssh`插件,可以在win的vscode编辑器享受linux的环境。
|
||||
|
||||
|
||||
|
||||
## 第三节
|
||||
|
||||
### 基本概念
|
||||
@@ -216,9 +193,9 @@ hello.c:6:9: warning: unused variable ‘i’ [-Wunused-variable]
|
||||
|
||||
```
|
||||
|
||||
* 例如说这个变量`i`定义了但是没用上,就是你清楚来龙去脉可以忽略的警告。
|
||||
* 而`malloc`那个警告就是在告诉你`malloc`所属的`stdlib.h`库未引入。
|
||||
* C语言程序往往如果能把警告都消除,错误也能解决。例如:
|
||||
- 例如说这个变量`i`定义了但是没用上,就是你清楚来龙去脉可以忽略的警告。
|
||||
- 而`malloc`那个警告就是在告诉你`malloc`所属的`stdlib.h`库未引入。
|
||||
- C语言程序往往如果能把警告都消除,错误也能解决。例如:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
@@ -270,20 +247,14 @@ cc a.c -o a
|
||||
fopen():No such file or directory
|
||||
```
|
||||
|
||||
|
||||
|
||||
##### 2. 以函数为单位来进行程序编写
|
||||
|
||||
`main`是特殊的定义,其实就是一个正在运行的线程。其实对于内核而言,是只有进程的概念,且与我们理解的进程、线程不一样。
|
||||
|
||||
|
||||
|
||||
##### 3. 声明部分+实现部分
|
||||
|
||||
早期的编译器要求变量先定义后使用。
|
||||
|
||||
|
||||
|
||||
##### 4. `return 0/exit(0)`
|
||||
|
||||
结束当前进程,是给父进程看的。
|
||||
@@ -303,12 +274,8 @@ Hello world!
|
||||
|
||||
在我本地无法复现,新版本可能改了。
|
||||
|
||||
|
||||
|
||||
##### 5. 多用空格空行
|
||||
|
||||
|
||||
|
||||
##### 6. 添加注释
|
||||
|
||||
```c
|
||||
@@ -328,25 +295,14 @@ func(){
|
||||
#endif
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 算法
|
||||
|
||||
解决问题的方法。(流程图,NS图,FSM有限状态机)
|
||||
|
||||
|
||||
|
||||
#### 程序
|
||||
|
||||
用某种语言实现算法
|
||||
|
||||
|
||||
|
||||
#### 进程
|
||||
|
||||
|
||||
|
||||
#### 防止写越界,防止内存泄漏,谁打开谁关闭,谁申请谁释放
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [第二章 数据类型,运算符和表达式](#第二章-数据类型运算符和表达式)
|
||||
- [数据类型(基本数据类型)](#数据类型基本数据类型)
|
||||
@@ -13,10 +14,6 @@
|
||||
- [表达式和语句的区别](#表达式和语句的区别)
|
||||
- [运算符相关代码](#运算符相关代码)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 第二章 数据类型,运算符和表达式
|
||||
|
||||
## 数据类型(基本数据类型)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [第三章 输入输出专题](#第三章-输入输出专题)
|
||||
- [内容](#内容)
|
||||
@@ -6,26 +7,22 @@
|
||||
- [`printf`](#printf)
|
||||
- [`scanf`](#scanf)
|
||||
- [字符输入输出函数](#字符输入输出函数)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- [字符串输入输出函数](#字符串输入输出函数)
|
||||
- [练习专题](#练习专题)
|
||||
- [夸脱水](#夸脱水)
|
||||
- [三角形面积](#三角形面积)
|
||||
- [求根公式](#求根公式)
|
||||
|
||||
# 第三章 输入输出专题
|
||||
|
||||
input & output -> I/O(标准IO,文件IO)
|
||||
|
||||
|
||||
|
||||
## 内容
|
||||
|
||||
1. 格式化输入输出函数:`scanf`, `printf`
|
||||
2. 字符输入输出函数:`getchar`, `putchar`
|
||||
3. 字符串输入输出函数:`gets(!)`,`puts`
|
||||
|
||||
|
||||
|
||||
## 格式化输入输出函数
|
||||
|
||||

|
||||
@@ -39,8 +36,6 @@ int printf(const char *format, ...);
|
||||
format: "%【修饰符】格式字符",参照图片标准输出修饰符和格式字符
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 有关`l`修饰符的提醒
|
||||
|
||||
```C
|
||||
@@ -63,16 +58,12 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
传输一个5G的文件
|
||||
|
||||
```c
|
||||
5LL*1204LL*1204LL*1204LL
|
||||
```
|
||||
|
||||
|
||||
|
||||
定义一个宏,表示一年有多少秒
|
||||
|
||||
```c
|
||||
@@ -80,16 +71,12 @@ int main()
|
||||
#define SEC_YEAR (60LL * 60LL * 24LL * 365LL)
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 函数 变参与定参重载的区别
|
||||
|
||||
- 变参:编译器只报警告,函数自己都不知道自己有多少个参数
|
||||
|
||||
- 定参重载:编译报错
|
||||
|
||||
|
||||
|
||||
- `\n`的作用
|
||||
|
||||
强制刷新缓冲区,以死循环调试举例。
|
||||
@@ -105,8 +92,6 @@ while (1)
|
||||
printf("[%s:%d]after while().\n", __FUNCTION__, __LINE__);
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 完整代码
|
||||
|
||||
```c
|
||||
@@ -200,8 +185,6 @@ int main()
|
||||
#define SEC_YEAR (60LL * 60LL * 24LL * 365LL)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `scanf`
|
||||
|
||||
```c
|
||||
@@ -211,8 +194,6 @@ format:抑制符*
|
||||
放在循环结构中时要注意能否接收到正常内容
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 完整代码
|
||||
|
||||
```c
|
||||
@@ -301,8 +282,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 字符输入输出函数
|
||||
|
||||
```c
|
||||
@@ -357,8 +336,6 @@ char *fgets(char *s, int size, FILE *stream);// 最多读到'size-1'个
|
||||
|
||||
`getline`是`GNU libc`的方言,可以动态内存保证读取一整行。
|
||||
|
||||
|
||||
|
||||
## 练习专题
|
||||
|
||||
### 夸脱水
|
||||
@@ -474,4 +451,3 @@ void root(void)
|
||||
printf("x2 = %f\n", x2);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [流程控制](#流程控制)
|
||||
- [关键字](#关键字)
|
||||
- [详解选择](#详解选择)
|
||||
@@ -26,29 +27,22 @@
|
||||
- [11](#11)
|
||||
- [12](#12)
|
||||
|
||||
|
||||
# 流程控制
|
||||
|
||||
1. 顺序,选择,循环
|
||||
2. NS图,流程图(工具:Visio,Dia)
|
||||
3. 简单结构与复杂结构:自然流程
|
||||
|
||||
|
||||
|
||||
- 顺序:语句逐句执行
|
||||
- 选择:出现了一种以上的情况
|
||||
- 循环:在某个条件成立的情况下,重复执行某个动作
|
||||
|
||||
|
||||
|
||||
## 关键字
|
||||
|
||||
- 选择:`if-else`,`switch-case`
|
||||
- 循环:`while`,`do-while`,`for`,`if-goto`
|
||||
- 辅助控制:`continue`,`break`
|
||||
|
||||
|
||||
|
||||
## 详解选择
|
||||
|
||||
### `if-else`
|
||||
@@ -156,8 +150,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `switch-case`
|
||||
|
||||
```c
|
||||
@@ -243,8 +235,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 详解循环
|
||||
|
||||
### `while`
|
||||
@@ -255,8 +245,6 @@ while(exp)
|
||||
loop;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `do-while`
|
||||
|
||||
```c
|
||||
@@ -268,8 +256,6 @@ do
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `for`
|
||||
|
||||
```c
|
||||
@@ -278,15 +264,11 @@ for(exp1;exp2;exp3)
|
||||
loop;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `goto`
|
||||
|
||||
- 慎重使用`if-goto`
|
||||
- `goto`实现的是 无条件的跳转,且不能跨函数跳转
|
||||
|
||||
|
||||
|
||||
### 死循环
|
||||
|
||||
```c
|
||||
@@ -296,16 +278,10 @@ for(;;);
|
||||
|
||||
`ctrl + c`杀掉死循环。
|
||||
|
||||
|
||||
|
||||
### 辅助控制
|
||||
|
||||
`break`,`continue`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 练习专题
|
||||
|
||||
### 1
|
||||
@@ -364,8 +340,6 @@ for(;;);
|
||||
>
|
||||
> F
|
||||
|
||||
|
||||
|
||||
### 10
|
||||
|
||||
> 包括钻石型
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [数组](#数组)
|
||||
- [一维数组](#一维数组)
|
||||
@@ -21,19 +22,14 @@
|
||||
- [单词计数](#单词计数)
|
||||
- [多维数组](#多维数组)
|
||||
|
||||
|
||||
# 数组
|
||||
|
||||
构造类型之一,连续存放。
|
||||
|
||||
|
||||
|
||||
> [!warning]
|
||||
>
|
||||
> 时间关系,大量的练习题,没有做笔记,只记录了题目。自己思考加看课程足矣。
|
||||
|
||||
|
||||
|
||||
## 一维数组
|
||||
|
||||
1. 定义
|
||||
@@ -57,8 +53,6 @@
|
||||
|
||||
5. 数组越界
|
||||
|
||||
|
||||
|
||||
### 练习部分
|
||||
|
||||
#### 斐波那契数列前10项
|
||||
@@ -230,8 +224,6 @@ static void primer(void)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 二维数组
|
||||
|
||||
1. 定义,初始化
|
||||
@@ -285,10 +277,6 @@ static void primer(void)
|
||||
|
||||
`a+1`跨越了行而不是单个元素。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 练习部分
|
||||
|
||||
#### 行列互换
|
||||
@@ -299,10 +287,6 @@ static void primer(void)
|
||||
|
||||
#### 矩阵乘积
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 字符数组
|
||||
|
||||
1. 定义,初始化,存储特点
|
||||
@@ -316,8 +300,6 @@ static void primer(void)
|
||||
|
||||
3. 常用函数
|
||||
|
||||
|
||||
|
||||
### 常用函数
|
||||
|
||||
1. `strlen`和`sizeof`
|
||||
@@ -375,8 +357,6 @@ static void primer(void)
|
||||
// out:hello world
|
||||
```
|
||||
|
||||
|
||||
|
||||
4. `strcmp`与`strncmp`
|
||||
|
||||
```c
|
||||
@@ -387,17 +367,12 @@ static void primer(void)
|
||||
// 指定比较前5个字符
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 练习部分
|
||||
|
||||
#### 单词计数
|
||||
|
||||
|
||||
|
||||
## 多维数组
|
||||
|
||||
```c
|
||||
int a[2][3][4];
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [指针](#指针)
|
||||
- [变量与地址](#变量与地址)
|
||||
@@ -16,7 +17,6 @@
|
||||
- [指针数组与数组指针](#指针数组与数组指针)
|
||||
- [多级指针](#多级指针)
|
||||
|
||||
|
||||
# 指针
|
||||
|
||||
## 变量与地址
|
||||
@@ -27,8 +27,6 @@
|
||||
|
||||
`100`是存放在这个地址的变量的值。
|
||||
|
||||
|
||||
|
||||
## 指针与指针变量
|
||||
|
||||
```c
|
||||
@@ -39,14 +37,10 @@ int **q = &p;
|
||||
|
||||
p是一个指针变量,他所存放的值是指针,指向另一个变量`i`的地址。
|
||||
|
||||
|
||||
|
||||
## 直接访问与间接访问
|
||||
|
||||
同样对于上面那个存放值为`100`的变量,既可以通过`i`直接访问,也可以通过`*p, **q`来间接访问。
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -122,8 +116,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 空指针与野指针
|
||||
|
||||
- 野指针:`int *p = 0x14532534`,不确定这个地址的情况,盲目的指过去,那么读或者写都是非法的。
|
||||
@@ -147,16 +139,12 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 空类型
|
||||
|
||||
`void *q`
|
||||
|
||||
万能类型。
|
||||
|
||||
|
||||
|
||||
## 定义与初始化的书写规则
|
||||
|
||||
```c
|
||||
@@ -164,13 +152,9 @@ int *p;
|
||||
int* p;
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 指针运算
|
||||
|
||||
`&` ` *` 关系运算 `++` `--`
|
||||
|
||||
|
||||
`&` `*` 关系运算 `++` `--`
|
||||
|
||||
## 指针与数组
|
||||
|
||||
@@ -269,8 +253,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 指针与二维数组
|
||||
|
||||
```c
|
||||
@@ -326,8 +308,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 指针与字符数组
|
||||
|
||||
```c
|
||||
@@ -387,8 +367,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## const 与指针
|
||||
|
||||
- 常量指针:**指向常量的指针**
|
||||
@@ -494,10 +472,6 @@ int main()
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 指针数组与数组指针
|
||||
|
||||
- 数组指针:指向数组的**指针**。
|
||||
@@ -512,8 +486,6 @@ int main()
|
||||
|
||||
如:`int *arr[3];` 看成 `int *[3] arr;`
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -552,9 +524,4 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 多级指针
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [函数](#函数)
|
||||
- [函数的定义](#函数的定义)
|
||||
@@ -16,15 +17,12 @@
|
||||
- [函数指针数组](#函数指针数组)
|
||||
- [指向指针函数的函数指针数组](#指向指针函数的函数指针数组)
|
||||
|
||||
|
||||
# 函数
|
||||
|
||||
## 函数的定义
|
||||
|
||||
数据类型 函数名 ( 【数据类型 形参名,数据类型 形参,...】 )
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -45,8 +43,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -70,8 +66,6 @@ void print_hello(void)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 函数的传参
|
||||
|
||||
值传递
|
||||
@@ -127,10 +121,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 函数的调用
|
||||
|
||||
### 嵌套调用
|
||||
@@ -170,8 +160,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 递归调用
|
||||
|
||||
```c
|
||||
@@ -229,10 +217,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 函数与数组
|
||||
|
||||
### 一维数组
|
||||
@@ -253,8 +237,6 @@ int *p = a;
|
||||
| *p | int |
|
||||
| p+1 | int* |
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -310,8 +292,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 二维数组
|
||||
|
||||
```c
|
||||
@@ -326,8 +306,6 @@ int (*q)[N] = a;
|
||||
// 行指针
|
||||
```
|
||||
|
||||
|
||||
|
||||
| 传参 | 类型 |
|
||||
| -------------------------- | -------------------------------------- |
|
||||
| `a[i][j]` | int |
|
||||
@@ -336,9 +314,9 @@ int (*q)[N] = a;
|
||||
| `p[i]` | ~~int [N] *~~ 正确答案: int |
|
||||
| `*p` | ~~int [N] *~~ 正确答案: int |
|
||||
| `q[i][j]` | int |
|
||||
| `*q` | ~~int [N] *~~ 正确答案: int * |
|
||||
| `*q` | ~~int [N] *~~ 正确答案: int* |
|
||||
| `q` | int (*) [N] |
|
||||
| `p+3` | ~~int [N] *~~ 正确答案: int * |
|
||||
| `p+3` | ~~int [N] *~~ 正确答案: int* |
|
||||
| `q+2` | ~~int [N] *~~ 正确答案: int (*) [N] |
|
||||
|
||||
```c
|
||||
@@ -421,10 +399,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 字符数组
|
||||
|
||||
```c
|
||||
@@ -470,10 +444,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 函数与指针
|
||||
|
||||
### 指针函数
|
||||
@@ -484,8 +454,6 @@ int main()
|
||||
|
||||
如:`int * fun(int);`
|
||||
|
||||
|
||||
|
||||
### 函数指针
|
||||
|
||||
是一个**指针**,指向**函数**。
|
||||
@@ -494,8 +462,6 @@ int main()
|
||||
|
||||
如: `int (*p)(int);`
|
||||
|
||||
|
||||
|
||||
### 函数指针数组
|
||||
|
||||
由**函数指针**组成的数组。
|
||||
@@ -504,14 +470,10 @@ int main()
|
||||
|
||||
如: `int (*arr[N])(int);`
|
||||
|
||||
|
||||
|
||||
### 指向指针函数的函数指针数组
|
||||
|
||||
`int *(*funcp[N])(int)`
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -553,4 +515,3 @@ int main()
|
||||
exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [构造类型](#构造类型)
|
||||
- [结构体](#结构体)
|
||||
@@ -19,7 +20,6 @@
|
||||
- [枚举](#枚举)
|
||||
- [typedef](#typedef)
|
||||
|
||||
|
||||
# 构造类型
|
||||
|
||||
## 结构体
|
||||
@@ -39,26 +39,16 @@ struct 结构体名
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 嵌套定义
|
||||
|
||||
### 定义变量(变量,数组,指针),初始化及成员引用
|
||||
|
||||
|
||||
|
||||
成员引用: 变量名. 成员名,指针->成员名,(*指针).成员名
|
||||
|
||||
|
||||
|
||||
### 结构体占用的内存空间大小
|
||||
|
||||
|
||||
|
||||
### 函数传参(值,地址)
|
||||
|
||||
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -175,10 +165,6 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
> 跳过
|
||||
|
||||
## 共用体
|
||||
@@ -196,8 +182,6 @@ union 共用体名
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 嵌套定义
|
||||
|
||||
### 定义变量(变量,数组,指针),初始化及成员引用
|
||||
@@ -208,12 +192,6 @@ union 共用体名
|
||||
|
||||
### 位域
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 枚举
|
||||
|
||||
```c
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [动态内存管理](#动态内存管理)
|
||||
- [函数传参相关问题](#函数传参相关问题)
|
||||
- [关于 free](#关于-free)
|
||||
|
||||
|
||||
# 动态内存管理
|
||||
|
||||
```` c
|
||||
@@ -14,12 +14,8 @@ void free(void *ptr);
|
||||
void *realloc(void *ptr, size_t size); // 重新分配空间
|
||||
````
|
||||
|
||||
|
||||
|
||||
原则:谁申请谁释放。
|
||||
|
||||
|
||||
|
||||
## 函数传参相关问题
|
||||
|
||||
1. 要么用二级指针
|
||||
@@ -65,10 +61,6 @@ int main()
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 关于 free
|
||||
|
||||
`free`操作没有扣掉那块内存,没有改变那块内存的值,也没有改变指针的指向。
|
||||
@@ -110,6 +102,3 @@ int main()
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
`make`会优先使用`makefile`,发布的项目一般是一个`Makefile`,方便用户写自己的`makefile`。
|
||||
|
||||
|
||||
|
||||
## 参考资料
|
||||
|
||||
[跟我一起写Makefile — 跟我一起写Makefile 1.0 文档 (seisman.github.io)](https://seisman.github.io/how-to-write-makefile/)
|
||||
@@ -1,14 +1,14 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [数据结构](#数据结构)
|
||||
- [架构梳理](#架构梳理)
|
||||
- [静态库与动态库](#静态库与动态库)
|
||||
- [静态库](#静态库)
|
||||
- [以链式双向链表的`lib2`为例。](#以链式双向链表的lib2为例)
|
||||
- [以链式双向链表的`lib2`为例](#以链式双向链表的lib2为例)
|
||||
- [动态库](#动态库)
|
||||
- [还是以`lib2`为例。](#还是以lib2为例)
|
||||
- [以链式存储栈为例,`libstack`依赖`libllist`。](#以链式存储栈为例libstack依赖libllist)
|
||||
|
||||
- [还是以`lib2`为例](#还是以lib2为例)
|
||||
- [以链式存储栈为例,`libstack`依赖`libllist`](#以链式存储栈为例libstack依赖libllist)
|
||||
|
||||
# 数据结构
|
||||
|
||||
@@ -52,8 +52,6 @@
|
||||
2. 球钟算法
|
||||
三个栈,1h,5min,1min。27个球,过了多久队列里又是1到27的顺序。
|
||||
|
||||
|
||||
|
||||
- 树状(1:N)
|
||||
|
||||
**递归**。**递归**转**非递归**。
|
||||
@@ -87,34 +85,24 @@
|
||||
|
||||
先加中,或者,中加后,都可以逆推出树。先加后不行。
|
||||
|
||||
|
||||
|
||||
- 平衡:
|
||||
|
||||
有很多种条件判定。
|
||||
|
||||
这棵树的左右子树个数差值为1。
|
||||
|
||||
|
||||
|
||||
- 广义表
|
||||
|
||||
`( root ( left ) ( right) )`,进行嵌套。
|
||||
|
||||
|
||||
|
||||
- 搜索树
|
||||
|
||||
空间换时间,查找是**o(1)**。
|
||||
|
||||
**课后作业:词频统计**
|
||||
|
||||
|
||||
|
||||
- 图(N:M)
|
||||
|
||||
|
||||
|
||||
## 静态库与动态库
|
||||
|
||||
- 静态库:
|
||||
@@ -124,8 +112,6 @@
|
||||
- 公交车,只能在指定的路径。
|
||||
- 运行时引入,占用运行时间。
|
||||
|
||||
|
||||
|
||||
### 静态库
|
||||
|
||||
1. `libxx.a`
|
||||
@@ -140,9 +126,7 @@
|
||||
5. `ldd -print shared libirary dependencies`
|
||||
打印所用到的动态库的内容
|
||||
|
||||
|
||||
|
||||
#### 以链式双向链表的`lib2`为例。
|
||||
#### 以链式双向链表的`lib2`为例
|
||||
|
||||
```bash
|
||||
*[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ldd ./main
|
||||
@@ -180,10 +164,9 @@
|
||||
1 std1 77 15
|
||||
0 std0 83 86
|
||||
```
|
||||
|
||||
这时`main.c`路径下都不需要`llist.c`和`llist.h`了,`#include`时也从`"llist.h"`变为`<llist.h>`。
|
||||
|
||||
|
||||
|
||||
### 动态库
|
||||
|
||||
1. `libxx.so`
|
||||
@@ -203,10 +186,7 @@ cp xx.co ~/lib
|
||||
export LD_LIBRARY_PATH= ~/lib
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 还是以`lib2`为例。
|
||||
|
||||
#### 还是以`lib2`为例
|
||||
|
||||
```bash
|
||||
*[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls
|
||||
@@ -246,9 +226,7 @@ export LD_LIBRARY_PATH= ~/lib
|
||||
>
|
||||
> 当动态库和静态库重名,会优先链接**静态库**。
|
||||
|
||||
|
||||
|
||||
#### 以链式存储栈为例,`libstack`依赖`libllist`。
|
||||
#### 以链式存储栈为例,`libstack`依赖`libllist`
|
||||
|
||||
```bash
|
||||
*[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ls
|
||||
|
||||
@@ -11,4 +11,3 @@
|
||||
2. 输入设备
|
||||
|
||||
3. 并发
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [I/O操作](#io操作)
|
||||
- [标准IO](#标准io)
|
||||
- [文件IO/系统调用IO](#文件io系统调用io)
|
||||
- [文件描述符的概念](#文件描述符的概念)
|
||||
- [文件IO操作相关函数:](#文件io操作相关函数)
|
||||
- [文件IO操作相关函数](#文件io操作相关函数)
|
||||
- [例题:通过文件IO处理csv表格](#例题通过文件io处理csv表格)
|
||||
- [文件IO与标准IO的区别](#文件io与标准io的区别)
|
||||
- [IO的效率问题](#io的效率问题)
|
||||
@@ -17,7 +18,6 @@
|
||||
- [同步](#同步)
|
||||
- [/dev/fd/目录](#devfd目录)
|
||||
|
||||
|
||||
# I/O操作
|
||||
|
||||
输入输出是一切实现的基础。
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
优先使用**标准IO**,兼容性更好,还有合并系统调用的优势。
|
||||
|
||||
|
||||
|
||||
## 标准IO
|
||||
|
||||
```c
|
||||
@@ -205,23 +203,17 @@ FILE *tmpfile(void);
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 文件IO/系统调用IO
|
||||
|
||||
文件描述符(`fd`)是在文件IO中贯穿始终的类型。
|
||||
|
||||
|
||||
|
||||
### 文件描述符的概念
|
||||
|
||||
是一个整型数,是一个指针数组的下标。
|
||||
|
||||
优先使用当前可用范围内最小的。
|
||||
|
||||
|
||||
|
||||
### 文件IO操作相关函数:
|
||||
### 文件IO操作相关函数
|
||||
|
||||
- `open`
|
||||
- `close`
|
||||
@@ -305,8 +297,6 @@ off_t lseek(int fd, offt offset, int whence);
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 例题:通过文件IO处理csv表格
|
||||
|
||||
```csv
|
||||
@@ -320,8 +310,6 @@ off_t lseek(int fd, offt offset, int whence);
|
||||
|
||||
可以使用16进制查看工具
|
||||
|
||||
|
||||
|
||||
### 文件IO与标准IO的区别
|
||||
|
||||
区别:响应速度&吞吐量
|
||||
@@ -330,17 +318,11 @@ off_t lseek(int fd, offt offset, int whence);
|
||||
|
||||
响应速度快就文件IO,吞吐量大就标准IO。
|
||||
|
||||
|
||||
|
||||
> [!warning]
|
||||
> 二者不可混用
|
||||
|
||||
|
||||
|
||||
转换方法:`fileno`, `fdopen`
|
||||
|
||||
|
||||
|
||||
### IO的效率问题
|
||||
|
||||
#### 习题
|
||||
@@ -399,8 +381,6 @@ rm $dst
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 结果
|
||||
|
||||
```bash
|
||||
@@ -424,8 +404,6 @@ Max BUFSIZE before segfault: 8388608
|
||||
|
||||
在`ulimit -a`中,我的系统的`stack size`是`8192`,所以`BUFSIZE`不能超过`8192`,否则会段错误。与测试结果一致。
|
||||
|
||||
|
||||
|
||||
### 文件共享
|
||||
|
||||
多个任务共同操作一个文件或者协同完成任务
|
||||
@@ -465,8 +443,6 @@ p1->read -> p2->write
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 原子操作
|
||||
|
||||
指不可分割的操作
|
||||
@@ -475,8 +451,6 @@ p1->read -> p2->write
|
||||
|
||||
如`tmpnam`函数,产生文件名和创建文件是两步,会有并发问题。
|
||||
|
||||
|
||||
|
||||
### 程序中的重定向:`dup`, `dup2`
|
||||
|
||||
```c
|
||||
@@ -489,8 +463,6 @@ int dup(int oldfd);
|
||||
int dup2(int oldfd, int newfd);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 同步
|
||||
|
||||
同步内核层面的buffer和cache
|
||||
@@ -508,8 +480,6 @@ int ioctl(int fd, unsigned long request, ... /* arg */);
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### /dev/fd/目录
|
||||
|
||||
**虚目录**:显示当前进程的文件描述符信息
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [文件系统](#文件系统)
|
||||
- [目录和文件](#目录和文件)
|
||||
@@ -13,15 +14,12 @@
|
||||
- [函数之间正常的跳转](#函数之间正常的跳转)
|
||||
- [资源的获取及控制](#资源的获取及控制)
|
||||
|
||||
|
||||
# 文件系统
|
||||
|
||||
类`ls`的实现,如`myls -l -a -i -n`
|
||||
|
||||
`cmd --长格式 -短格式 非选项的传参`
|
||||
|
||||
|
||||
|
||||
## 目录和文件
|
||||
|
||||
1. 获取文件属性
|
||||
@@ -100,7 +98,6 @@ int fchmod(int fd, mode_t mode);
|
||||
2. `UFS`:
|
||||
缺点:不善于处理大量的小文件,因为每个文件都有一个`inode`,占用空间。
|
||||
|
||||
|
||||
> 面试题:
|
||||
> 不用比较,比较两个uint32_t的大小
|
||||
> 使用位图
|
||||
@@ -114,13 +111,11 @@ int fchmod(int fd, mode_t mode);
|
||||
|
||||
限制:不能给分区建立,不能给目录建立
|
||||
|
||||
|
||||
- 符号链接
|
||||
`ln -s bigfile_link bigfile_s`
|
||||
|
||||
优点:可以跨分区,可以给目录建立
|
||||
|
||||
|
||||
```c
|
||||
int link(const char *oldpath, const char *newpath);
|
||||
|
||||
@@ -275,8 +270,6 @@ long telldir(DIR *dirp);
|
||||
|
||||
作业:用另一套函数实现`mydu`
|
||||
|
||||
|
||||
|
||||
## 系统数据文件和信息
|
||||
|
||||
> 不同环境可能有区别,以具体查询为准,这里以Linux为例
|
||||
@@ -434,8 +427,6 @@ size_t strftime(char *s, size_t max, const char *format,
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 进程环境
|
||||
|
||||
### `main`函数
|
||||
@@ -444,8 +435,6 @@ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
|
||||
int main(int argc, char *argv[]);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 进程的终止
|
||||
|
||||
1. 正常终止:
|
||||
@@ -470,7 +459,6 @@ int main(int argc, char *argv[]);
|
||||
- 接到一个信号并终止
|
||||
- 最后一个线程对其取消请求作出响应
|
||||
|
||||
|
||||
```c
|
||||
/**
|
||||
* 注册一个函数,当进程终止时调用
|
||||
@@ -481,8 +469,6 @@ int main(int argc, char *argv[]);
|
||||
int atexit(void (*function)(void));// 钩子函数
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 命令行参数的分析
|
||||
|
||||
```c
|
||||
@@ -498,8 +484,6 @@ int getopt_long(int argc, char *const argv[], const char *optstring,
|
||||
const struct option *longopts, int *longindex);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 环境变量
|
||||
|
||||
**KEY = VALVE**
|
||||
@@ -525,14 +509,10 @@ int unsetenv(const char *name);
|
||||
int putenv(char *string);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### C程序的存储空间布局
|
||||
|
||||
`pmap`命令,查看进程空间布局
|
||||
|
||||
|
||||
|
||||
### 库
|
||||
|
||||
- 动态库
|
||||
@@ -549,8 +529,6 @@ int putenv(char *string);
|
||||
// Link with -ldl
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 函数之间正常的跳转
|
||||
|
||||
`goto`无法跨函数跳转。
|
||||
@@ -573,8 +551,6 @@ int setjmp(jmp_buf env);
|
||||
void longjmp(jmp_buf env, int val);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 资源的获取及控制
|
||||
|
||||
`ulimit -a`
|
||||
@@ -591,4 +567,3 @@ struct rlimit {
|
||||
rlim_t rlim_max; /* hard limit */
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 目录
|
||||
|
||||
- [目录](#目录)
|
||||
- [进程基本知识](#进程基本知识)
|
||||
- [进程标识符`pid`](#进程标识符pid)
|
||||
@@ -13,7 +14,6 @@
|
||||
- [守护进程](#守护进程)
|
||||
- [系统日志](#系统日志)
|
||||
|
||||
|
||||
# 进程基本知识
|
||||
|
||||
已经进入**多进程**阶段
|
||||
@@ -36,8 +36,6 @@ pid_t getpid(void);
|
||||
pid_t getppid(void);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 进程的产生
|
||||
|
||||
`pid_t fork();`
|
||||
@@ -68,8 +66,6 @@ pid_t getppid(void);
|
||||
pid_t vfork(void);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 进程的消亡及释放资源
|
||||
|
||||
```c
|
||||
@@ -90,8 +86,6 @@ wait4();
|
||||
池类算法:
|
||||
上游往池子里放任务,下游三个线程从池子里取任务。
|
||||
|
||||
|
||||
|
||||
## `exec`函数族
|
||||
|
||||
eg. `bash`进程创建`primer`进程
|
||||
@@ -172,8 +166,6 @@ int setregid(gid_t rgid, gid_t egid);
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 观摩课:解释器文件
|
||||
|
||||
> unix讲究机制而非策略
|
||||
@@ -188,8 +180,6 @@ int setregid(gid_t rgid, gid_t egid);
|
||||
|
||||
`#!`是一种约定俗成的标记,告诉系统这个脚本应该用什么解释器来执行。
|
||||
|
||||
|
||||
|
||||
## `system()`函数
|
||||
|
||||
```c
|
||||
@@ -202,8 +192,6 @@ int system(const char *command);
|
||||
|
||||
相当于`fork+exec+wait`的封装
|
||||
|
||||
|
||||
|
||||
## 进程会计
|
||||
|
||||
```c
|
||||
@@ -211,8 +199,6 @@ int system(const char *command);
|
||||
int acct(const char *filename);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 进程时间
|
||||
|
||||
```c
|
||||
@@ -229,8 +215,6 @@ struct tms{
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 守护进程
|
||||
|
||||
1. 守护进程`PPID`为1
|
||||
@@ -254,13 +238,10 @@ pid_t getpgrp(psid_t pid); //! 方言
|
||||
- 终端:
|
||||
我们接触的都是虚拟终端
|
||||
|
||||
|
||||
**单实例守护进程**:锁文件`/var/run/name.pid`
|
||||
|
||||
启动脚本文件:`/etc/rc*...`
|
||||
|
||||
|
||||
|
||||
## 系统日志
|
||||
|
||||
`syslogd`服务
|
||||
|
||||
@@ -299,3 +299,74 @@ struct timeval {
|
||||
此外都和标准信号一样
|
||||
|
||||
## 线程(强烈异步)
|
||||
|
||||
### 线程的概念
|
||||
|
||||
会话-->进程-->线程
|
||||
|
||||
一个正在运行的函数。
|
||||
|
||||
`main`函数可以叫做main线程,不应该说主线程,线程之间平等。
|
||||
|
||||
`posix`线程是一套标准,而不是实现。
|
||||
`openmp`线程。
|
||||
|
||||
例如,线程标识: `pthread_t`, 具体类型怎么实现是不知道的
|
||||
在linux环境,可以通过`ps axm`或者`ps -ax -L`查看线程信息。
|
||||
发现线程消耗了进程号。
|
||||
|
||||
```c
|
||||
#include <pthread.h>
|
||||
//* Compile and link with -pthread
|
||||
|
||||
/**
|
||||
* 比较两个pthread_t是否相等
|
||||
* @param: t1: pthread_t
|
||||
* @param: t2: pthread_t
|
||||
*
|
||||
* @return: 相等返回非0,不相等返回0
|
||||
*/
|
||||
int pthread_equal(pthread_t t1, pthread_t t2);
|
||||
|
||||
/**
|
||||
* 获取当前线程的pthread_t
|
||||
* @return: 当前线程的pthread_t
|
||||
*/
|
||||
pthread_t pthread_self(void);
|
||||
|
||||
```
|
||||
|
||||
### 线程的操作
|
||||
|
||||
创建,终止,取消,栈的清理
|
||||
|
||||
线程的调度取决于调度器策略。
|
||||
|
||||
```c
|
||||
#include <pthread.h>
|
||||
// Compile and link with -pthread
|
||||
|
||||
/**
|
||||
* 创建线程
|
||||
* @param: thread: 线程ID指针
|
||||
* @param: attr: 线程属性指针
|
||||
* NULL: 默认属性
|
||||
* @param: start_routine: 线程函数指针
|
||||
* void *(*)(void *)
|
||||
* @param: arg: 线程函数参数
|
||||
*
|
||||
* @return: 成功返回0,失败返回errCode
|
||||
* 建议使用strerror而非perror
|
||||
*/
|
||||
int pthread_create(pthread_t * thread,
|
||||
const pthread_attr_t *attr,
|
||||
void *(*start_routine)(void *),
|
||||
void *arg);
|
||||
|
||||
```
|
||||
|
||||
### 线程的同步
|
||||
|
||||
### 线程属性,线程同步的属性
|
||||
|
||||
### 重入,线程与信号,线程与`fork`
|
||||
|
||||
Reference in New Issue
Block a user