更新了文件名。开始了数据结构
This commit is contained in:
338
Chapter01/C1-绪论.md
Normal file
338
Chapter01/C1-绪论.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# 目录
|
||||
- [目录](#目录)
|
||||
- [第一章 绪论](#第一章-绪论)
|
||||
- [第一节](#第一节)
|
||||
- [C语言发展史](#c语言发展史)
|
||||
- [C语言特点](#c语言特点)
|
||||
- [C语言学习建议](#c语言学习建议)
|
||||
- [课程思路](#课程思路)
|
||||
- [课程平台](#课程平台)
|
||||
- [第二节](#第二节)
|
||||
- [神一般的`Hello world!`](#神一般的hello-world)
|
||||
- [源文件到可执行文件](#源文件到可执行文件)
|
||||
- [gcc](#gcc)
|
||||
- [make](#make)
|
||||
- [vim](#vim)
|
||||
- [第三节](#第三节)
|
||||
- [基本概念](#基本概念)
|
||||
- [以`Hello world`为例对写程序的思路提出如下要求](#以hello-world为例对写程序的思路提出如下要求)
|
||||
- [1. 头文件正确包含的重要性](#1-头文件正确包含的重要性)
|
||||
- [2. 以函数为单位来进行程序编写](#2-以函数为单位来进行程序编写)
|
||||
- [3. 声明部分+实现部分](#3-声明部分实现部分)
|
||||
- [4. `return 0/exit(0)`](#4-return-0exit0)
|
||||
- [5. 多用空格空行](#5-多用空格空行)
|
||||
- [6. 添加注释](#6-添加注释)
|
||||
- [算法](#算法)
|
||||
- [程序](#程序)
|
||||
- [进程](#进程)
|
||||
- [防止写越界,防止内存泄漏,谁打开谁关闭,谁申请谁释放](#防止写越界防止内存泄漏谁打开谁关闭谁申请谁释放)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 第一章 绪论
|
||||
|
||||
课程地址,[史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV18p4y167Md/?spm_id_from=333.999.0.0&vd_source=4e03f52e94cfa281cde032856b1f93a7)。
|
||||
|
||||
## 第一节
|
||||
|
||||
### C语言发展史
|
||||
|
||||
| 时间 | 发展 |
|
||||
| ---- | -------------------- |
|
||||
| 1960 | 原型A语言->ALGOL语言 |
|
||||
| 1963 | CPL语言 |
|
||||
| 1967 | BCPL |
|
||||
| 1967 | B语言 |
|
||||
| 1973 | C语言 |
|
||||
|
||||
|
||||
|
||||
### C语言特点
|
||||
|
||||
1. 基础性语言
|
||||
2. 语法间接、紧凑、方便、灵活
|
||||
3. 运算符,数据结构丰富
|
||||
4. 结构化,模块化编程
|
||||
5. 移植性好,执行效率高
|
||||
6. 允许直接对硬件操作
|
||||
|
||||
|
||||
|
||||
### C语言学习建议
|
||||
|
||||
1. 概念的正确性
|
||||
2. 动手能力
|
||||
3. 阅读优秀的程序段
|
||||
4. 大量练习,面试题
|
||||
|
||||
|
||||
|
||||
### 课程思路
|
||||
|
||||
1. 基础概念
|
||||
2. 数据类型,运算符和表达式
|
||||
3. 输入输出专题
|
||||
4. 流程控制
|
||||
5. 数组
|
||||
6. 指针
|
||||
7. 函数
|
||||
8. 构造类型
|
||||
9. 动态内存管理
|
||||
10. 调试工具(gdb,make)
|
||||
11. 常用库函数
|
||||
|
||||
|
||||
|
||||
### 课程平台
|
||||
|
||||
* 老师:64位的`redhat6`,`vim`,`gcc4.4.6(make)`
|
||||
* 本人:`WSL-debian`,`vscode(remote ssh)`,`gcc12.2.0(make)`,`ohmyzsh(theme:eastwood)`
|
||||
|
||||
我的`gcc`版本比较新,所以很多提示比较完善,老师这个课程是很早的课,那个时候的gcc提示没有现在厉害,所以还是要结合老师的视频的思路,在当时提示不完善的时候是如何手撕代码分析出来的。
|
||||
|
||||
|
||||
|
||||
## 第二节
|
||||
|
||||
### 神一般的`Hello world!`
|
||||
|
||||
```c
|
||||
//hello.c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if 0
|
||||
void main(void);
|
||||
void main(int argc, char **argv);// char *argv[]
|
||||
int main(int argc, char **argv);
|
||||
int main(void);
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello world!\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
用那种`main`得看编译器环境,目前在`linux`的`gcc`下,`int main(void);`常用,需要传参用`int main(int argc, char **argv);`。
|
||||
|
||||
|
||||
|
||||
### 源文件到可执行文件
|
||||
|
||||
#### gcc
|
||||
|
||||
C源文件=>预处理=>编译=>汇编=>链接=>可执行文件
|
||||
|
||||
> 所有`#`后面的代码都在预处理解决
|
||||
|
||||
```bash
|
||||
# 单步执行
|
||||
gcc -E hello.c > hello.i # 预处理生成hello.i
|
||||
gcc -S hello.i # 编译生成hello.s
|
||||
gcc -c hello.s # 汇编生成hello.o
|
||||
gcc hello.o -o hello # 链接生成hello
|
||||
./hello # 运行
|
||||
Hello world!
|
||||
|
||||
# 一次到位
|
||||
gcc hello.c # 得到a.out可执行文件
|
||||
# 指定名字
|
||||
gcc hello.c -o myhello # 得到myhello可执行文件
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### make
|
||||
|
||||
```bash
|
||||
$ make hello
|
||||
cc hello.c -o hello
|
||||
# cc就是make选择的编译器,这里是gcc
|
||||
$ ls
|
||||
hello hello.c
|
||||
```
|
||||
|
||||
|
||||
|
||||
### vim
|
||||
|
||||
老师对于常用的`.vimrc`做了一些介绍,笔者建议`vscode`的`remote-ssh`插件,可以在win的vscode编辑器享受linux的环境。
|
||||
|
||||
|
||||
|
||||
## 第三节
|
||||
|
||||
### 基本概念
|
||||
|
||||
#### 以`Hello world`为例对写程序的思路提出如下要求
|
||||
|
||||
##### 1. 头文件正确包含的重要性
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int *p = NULL;
|
||||
int i;
|
||||
p = malloc(sizeof(int));
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
printf("Hello world!\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
这里我的gcc版本比较新,所以和老师的不一致,总之老师的意思就是
|
||||
|
||||
> 不要忽略gcc的警告!!!
|
||||
|
||||
```bash
|
||||
# 通过 -Wall 参数让gcc显示全部警告
|
||||
# 注意'W'要大写
|
||||
$ gcc hello.c -Wall
|
||||
hello.c: In function ‘main’:
|
||||
hello.c:7:9: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
|
||||
7 | p = malloc(sizeof(int));
|
||||
| ^~~~~~
|
||||
hello.c:2:1: note: include ‘<stdlib.h>’ or provide a declaration of ‘malloc’
|
||||
1 | #include <stdio.h>
|
||||
+++ |+#include <stdlib.h>
|
||||
2 |
|
||||
hello.c:7:9: warning: incompatible implicit declaration of built-in function ‘malloc’ [-Wbuiltin-declaration-mismatch]
|
||||
7 | p = malloc(sizeof(int));
|
||||
| ^~~~~~
|
||||
hello.c:7:9: note: include ‘<stdlib.h>’ or provide a declaration of ‘malloc’
|
||||
hello.c:6:9: warning: unused variable ‘i’ [-Wunused-variable]
|
||||
6 | int i;
|
||||
| ^
|
||||
|
||||
```
|
||||
|
||||
* 例如说这个变量`i`定义了但是没用上,就是你清楚来龙去脉可以忽略的警告。
|
||||
* 而`malloc`那个警告就是在告诉你`malloc`所属的`stdlib.h`库未引入。
|
||||
* C语言程序往往如果能把警告都消除,错误也能解决。例如:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen("tmp", "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
fprintf(stderr, "fopen():%s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
puts("ok!");
|
||||
exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
这个程序运行报段错误,这个时候,查看一下警告就是问题所在。
|
||||
|
||||
```bash
|
||||
$ ./a
|
||||
[1] 1960 segmentation fault ./a
|
||||
|
||||
$ gcc a.c -Wall
|
||||
a.c: In function ‘main’:
|
||||
a.c:12:41: warning: implicit declaration of function ‘strerror’; did you mean ‘perror’? [-Wimplicit-function-declaration]
|
||||
12 | fprintf(stderr, "fopen():%s\n", strerror(errno));
|
||||
| ^~~~~~~~
|
||||
| perror
|
||||
a.c:12:35: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
|
||||
12 | fprintf(stderr, "fopen():%s\n", strerror(errno));
|
||||
| ~^ ~~~~~~~~~~~~~~~
|
||||
| | |
|
||||
| | int
|
||||
| char *
|
||||
| %d
|
||||
```
|
||||
|
||||
用`%s`需要的类型是`char *`,但是`strerror(errno)`的类型是`int`,它是所以是`int`,是因为C语言对没有找到原型的函数返回值都是`int`,所以根源在于`strerror`函数没有原型,没有引入需要的`string.h`库。加入这个库重新运行。
|
||||
|
||||
```bash
|
||||
[main][~/LinuxC/Chapter1/Section3]$ make a
|
||||
cc a.c -o a
|
||||
[main][~/LinuxC/Chapter1/Section3]$ ./a
|
||||
fopen():No such file or directory
|
||||
```
|
||||
|
||||
|
||||
|
||||
##### 2. 以函数为单位来进行程序编写
|
||||
|
||||
main`是特殊的定义,其实就是一个正在运行的线程。其实对于内核而言,是只有进程的概念,且与我们理解的进程、线程不一样。
|
||||
|
||||
|
||||
|
||||
##### 3. 声明部分+实现部分
|
||||
|
||||
早期的编译器要求变量先定义后使用。
|
||||
|
||||
##### 4. `return 0/exit(0)`
|
||||
|
||||
结束当前进程,是给父进程看的。
|
||||
|
||||
对于带有`return 0`的程序:
|
||||
|
||||
```bash
|
||||
[main][~/LinuxC/Chapter1/Section3]$ ./hello
|
||||
Hello world!
|
||||
[main][~/LinuxC/Chapter1/Section3]$ echo $?
|
||||
0
|
||||
```
|
||||
|
||||
如果不带`return 0`:
|
||||
|
||||
老师演示的返回值是13,是`printf`的返回的`Hello world!\n`的长度。
|
||||
|
||||
在我本地无法复现,新版本可能改了。
|
||||
|
||||
##### 5. 多用空格空行
|
||||
|
||||
##### 6. 添加注释
|
||||
|
||||
```c
|
||||
//单行注释
|
||||
|
||||
/*
|
||||
* 多行注释
|
||||
* 多行注释
|
||||
* 多行注释
|
||||
*/
|
||||
|
||||
//大段的注释
|
||||
#if 0
|
||||
func(){
|
||||
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
#### 算法
|
||||
|
||||
解决问题的方法。(流程图,NS图,FSM有限状态机)
|
||||
|
||||
#### 程序
|
||||
|
||||
用某种语言实现算法
|
||||
|
||||
#### 进程
|
||||
|
||||
#### 防止写越界,防止内存泄漏,谁打开谁关闭,谁申请谁释放
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user