嵌入式linux学习笔记之c编程基础
2019-07-13 00:28 发布
生成海报
c编程基础包括编辑器Vi,编译器gcc,调试器gdb,项目管理器make。(另编辑器emacs,autotools等略)
1文本编辑
Linux提供了一系列功能强大的编辑器,如vi和Emacs。
1-1 vi 是linux系统的第一个全屏幕交互式编辑器,从诞生到现在一直得到广大用户青睐。
vi 有3种工作模式,分别是 命令行模式、插入模式、底行模式。
命令行模式:最初进入的一般模式,该模式下可以移动光标进行浏览,整行删除,但无法编辑文字。 插入模式:只有在该模式下,用户才能进行文字的编辑输入,用户可以使用[ESC]键回到命令行模式。 底行模式:该模式下,光标位于屏幕底行,用户可以进行文件保存或退出操作,也可以设置编辑环境,如寻找字符串、列出行号。
1-1-1文本编辑
1. vi hello.c
2. 键入i进入插入模式
3. 编辑
4. 键入[ESC]退入到命令行模式
5. 键入:wq保存退出
1-1-2 命令行模式功能键:
• yy: 复制当前光标所在行
• [n]yy:n为数字,复制当前光标开始的n行
• p: 粘贴复制的内容到光标所在行
• dd:删除当前光标所在行
• [n]dd:删除当前光标所在行开始的n行
• /name:查找光标之后的名为“name”的字符串
• G:光标移动到文件尾(注意是大写)
• u: 取消前一个动作(注意是小写)
1-1-3底行模式功能键:
• :w 保存
• :q 退出vi(系统会提示保存修改)
• :q! 强行退出(对修改不做保存)
• :wq 保存后退出
• :w [filename] 另存为filename的文件
• :set nu 显示行号
• :set nonu 取消行号
1-1-4插入模式功能键:
只有一个,esc退出到命令行模式。
2.GCC( GNU C Compiler) 程序编译:将C、C++语言程序、汇编程序编译、链接成可 执行文件。GCC编译器能将C、C++语言源程序、汇编程序编译、链接成可执行文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。 2-1 编译过程课细分四步骤:
预处理:Pre-processing
编译:Compiling
汇编:Assembling
链接:Linking
例:使用gcc编译命令,编译hello.c生成可执行文件hello,并运行hello。以下是两种实现方法。
(1)命令: #gcc hello.c -o hello
(2)预处理:gcc -E hello.c -o hello.i
编译:gcc -S hello.i -o hello.s
汇编:gcc -c hello.s -o hello.o
链接:gcc hello.o -o hello
2-2 Gcc通过后缀来区别输入文件的类别:
.c为后缀的文件: C语言源代码文件 .a为后缀的文件: 是由目标文件构成的库文件 .C,.cc或.cxx 为后缀的文件: 是C++源代码文件 .h为后缀的文件: 头文件 .i 为后缀的文件: 是已经预处理过的C源代码文件 .ii为后缀的文件: 是已经预处理过的C++源代码文件 .o为后缀的文件: 是编译后的目标文件 .s为后缀的文件: 是汇编语言源代码文件 .S为后缀的文件: 是经过预编译的汇编语言源代码文件。
语法:gcc 编译器的编译选项要编译的文件名
举例:
hello.c:
#include
int main(void)
{
printf (“Hello world!
”);
return 0;
}
编译和运行这段程序:
# gcc hello.c -o hello
# ./hello
输出: Hello world!
2-3 gcc最基本的用法是∶gcc [options] [filenames]
options:编译器所需要的编译选项 filenames: 要编译的文件名。
gcc编译器的编译选项大约有100多个,其中多数我们根本就用不到,这里只介绍其中最基本、最常用的参数。
-o output_filename:确定可执行文件的名称为output_filename。如果不给出这个选项,gcc就给出预设的可执行文件a.out。(演示) -c:只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件。 -g:产生调试工具(GNU的gdb)所必要的符号信息,要想对编译出的程序进行调试,就必须加入这个选项。 -O,对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。 -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。 - l dirname: 将dirname所指出的目录加入到程序头文件 目录列表中。
1、#include 2、#include"B.h" 对于< >,预处理文件cpp会在系统预设的头文件目录(如/usr/include)中搜寻头文件;对于" " ,cpp在当前的目录中去寻找头文件。 这个选项的作用是告诉cpp,如果当前目录中,没有找到需要的文件,就到指定的dirname目录中去寻找。 例如:gcc foo.c -l /home/include -o foo - L dirname: 将dirname所指出的目录加入到库文件 目录列表中。
默认情况下,连接程序ld在系统设置的预存路径中(如/usr/lib)中搜寻所需的库文件,这个选项的作用是告诉连接程序,首先到就到-L指定的目录中去寻找,然后到系统预设路径中寻找。 -lname:在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如,-lm表示连接名为“libm.a”的数学函数库。
例:gcc foo.c -L /home/lib -lfoo -o foo -static:静态链接库文件
例:gcc –static hello.c -o hello 库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a。当使用静态库时,连接器 找出程序所需的函数,然后将它们拷贝到可执行文件,一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言, 就不是这样,动态库会在执行程序内留下一个标记‘指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux 下进行连接的缺省操作是首先连接动态库。 演示:静态链接与动态链接可执行文件大小比较 -Wall:生成所有警告信息 -w:不生成任何警告信息 -DMACRO: 定义MACRO 宏,等效于在程序中使用#define MACRO
3.GDB 程序调试功能:
启动被调试程序
让被调试的程序在制定位置停住 当程序被停住时,可以检查程序状态(如变量值)
启动GDB:
gdb 调试程序名; gdb ,
file 调试程序名。
使用过程:
gcc -g test. c test //编译生成可执行文件,要带上-g gdb test // 启动GDB break main // 在main 函数设置断点 run // 运行程序 next // 单步运行: continue // 继续运行
GDB命令
list(l) //查看程序 break(b) // 函数名在某函数入口处添加断点 break(b)
// 行号在指定行添加断点 break(b) // 文件名:行号在指定文件的指定行添加断点 break(b)
// 行号if 条件当条件为真时,指定行号处断点生效,例b 5 if i=10,当i等于10时第5行断点生效 info break // 查看所有设置的断点 delete
// 断点编号删除断点 run(r)
// 开始运行程序 next(n) // 单步运行程序(不进入子函数) step(s)
// 单步运行程序(进入子函数) continue(c)
// 继续运行程序 print(p)
// 变量名查看指定变量值 finish
// 运行程序,直到当前函数结束 watch
// 变量名对指定变量进行监控 quit(q) // 退出gdb
4.Makefile 工程管理:使整个软件工程的编译、链接只需要一个命令就可以完成
make在执行时, 需要一个命名为Makefile的文件。Makefile文件描述了整个工程的编译,连接等规则。其中包括:工程中的
哪些源文件需要编译以及如何编译;需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要得可执行文件。
举例:
hello: main.o func1.o func2.o
gcc main.o func1.o func2.o -o hello
main.o : main.c
gcc –c main.c
func1.o : func1.c
gcc –c func1.c
func2.o : func2.c
gcc –c func2.c
.PHONY : clean
clean :
rm –f hello main.o func1.o func2.o
规则:用于说明如何生成一个或多个目标文件,
规则格式如下:
targets : prerequisites
command
目标依赖命令
main.o : main.c
gcc –c main.c
目标?依赖?命令?
**命令需要以【TAB】键开始**
目标
在Makefile 中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来的,所 以一定要让make知道你的最终目标是什么。
一般来说,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标。
文件名
make命令默认在当前目录下寻找名字为makefile或者Makefile的工程文件,当名字不为这两者之一时,可以使用如下方法指
定: make –f 文件名
伪目标
Makefile中把那些没有任何依赖只有执行动作的目标称为“伪目标”(phonytargets)。
.PHONY : clean
clean :
rm –f hello main.o func1.o func2.o
“.PHONY” 将“clean”目标声明为伪目标
变量
hello: main.o func1.o func2.o
gcc main.o func1.o func2.o -o hello
思考1:如果要为hello目标添加一个依赖,如:func3.o,该如 何修改?
答案1:
hello: main.o func1.o func2.o func3.o
gcc main.o func1.o func2.o func3.o -o hello
答案2:
obj=main.o func1.o func2.o func3.o
hello: $(obj)
gcc $(obj) -o hello
在makefile中,存在系统默认的自动化变量
^:代表所有的依赖文件
$@:代表目标
$<:代表第一个依赖文件
例:
hello: main.o func1.o func2.o
gcc main.o func1.o func2.o -o hello
=》
hello: main.o func1.o func2.o
gcc $^ -o $@
杂项
Makefile中“#”字符后的内容被视作注释。
hello: hello.c
@gcc hello.c –o hello
@:取消回显
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮