8.6 KiB
目录
第一章 绪论
课程地址,史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】_哔哩哔哩_bilibili。
第一节
C语言发展史
| 时间 | 发展 |
|---|---|
| 1960 | 原型A语言->ALGOL语言 |
| 1963 | CPL语言 |
| 1967 | BCPL |
| 1967 | B语言 |
| 1973 | C语言 |
C语言特点
- 基础性语言
- 语法间接、紧凑、方便、灵活
- 运算符,数据结构丰富
- 结构化,模块化编程
- 移植性好,执行效率高
- 允许直接对硬件操作
C语言学习建议
- 概念的正确性
- 动手能力
- 阅读优秀的程序段
- 大量练习,面试题
课程思路
- 基础概念
- 数据类型,运算符和表达式
- 输入输出专题
- 流程控制
- 数组
- 指针
- 函数
- 构造类型
- 动态内存管理
- 调试工具(gdb,make)
- 常用库函数
课程平台
- 老师:64位的
redhat6,vim,gcc4.4.6(make) - 本人:
WSL-debian,vscode(remote ssh),gcc12.2.0(make),ohmyzsh(theme:eastwood)
我的gcc版本比较新,所以很多提示比较完善,老师这个课程是很早的课,那个时候的gcc提示没有现在厉害,所以还是要结合老师的视频的思路,在当时提示不完善的时候是如何手撕代码分析出来的。
第二节
神一般的Hello world!
//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源文件=>预处理=>编译=>汇编=>链接=>可执行文件
所有
#后面的代码都在预处理解决
# 单步执行
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
$ 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. 头文件正确包含的重要性
#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的警告!!!
# 通过 -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语言程序往往如果能把警告都消除,错误也能解决。例如:
#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);
}
这个程序运行报段错误,这个时候,查看一下警告就是问题所在。
$ ./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库。加入这个库重新运行。
[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的程序:
[main][~/LinuxC/Chapter1/Section3]$ ./hello
Hello world!
[main][~/LinuxC/Chapter1/Section3]$ echo $?
0
如果不带return 0:
老师演示的返回值是13,是printf的返回的Hello world!\n的长度。
在我本地无法复现,新版本可能改了。
5. 多用空格空行
6. 添加注释
//单行注释
/*
* 多行注释
* 多行注释
* 多行注释
*/
//大段的注释
#if 0
func(){
}
#endif
算法
解决问题的方法。(流程图,NS图,FSM有限状态机)
程序
用某种语言实现算法