摘要:此为学习Linux课程中关于gcc编译器的一些总结,方便以后查阅。
用集成的编程软件很难了解到程序背后编译器对代码编译过程的具体步骤,所以在这里进行手动编译可以让人更直观的了解到编译器编译代码的过程。
首先,我们来写一段程序,当然是我们最熟悉的它啦!Hello World:
1 |
|
并保存为test.c
第一种编译方式
然后我们到命令行中输入gcc test.c
直接回车后可以发现多了一个a.out的文件。
a.out就是刚刚生成的可执行文件,现在我们要执行它。
输入./a.out
即可执行它了,如下图所示
可以看到我们很顺利的就打印出了Hello world!
总结:
gcc <filename.c>
第二种编译方式
这是一种通过中间代码进行编译
输入gcc -c test.c
按下回车,可以看到多了一个以文件名.o命名的文件:
这是编译器用 -c 这个参数时单一生成的中间代码,但是中间代码是不可以执行的,我们需要进行链接生成可执行文件。
输入gcc -o test_1 test.o
(其中test_1为你自定义的文件名,test.o为上一步生成的中间文件),我们可以直接执行test_1来看看会得到一样的效果:
总结:
- gcc -c <filename.c>
- gcc -o
<filename.o>
但是我们在编写代码时不能所以都由自己写,需要用到写好的库文件时,该怎么用呢?
这里我们重新编写代码:
1 |
|
如果直接运行gcc -c test.c
会发现报错:
可以发现,凡是语法错误在编译的时候就会识别出来了,已经说明函数sqrt未被定义。可以看到解决方案,加上头文件。
1 |
|
然后编译gcc -c test.c
和gcc -o test test.o
后
发现调用别人的函数有两个要求,一是知道函数的原型,一般在头文件中就给出。二是函数会编译成库的形式,我需要来调用这个库的形式,需要告诉调用的库的名字是什么,所以这个问题是因为我们在链接的时候没有把库函数链接上。解决办法:
gcc -o test test.o -lm
(链接math.h不是-lmath而是-lm)
这个时候就编译成功了!
输入 man sqrt
可以查看手册,得到链接的参数。
第三种编译方式
测试多个文件怎么进行编译:
这里test.c为主程序,myfunc.c和myfunc.h为模块代码
test.c
:
1 |
|
myfunc.c
:
1 | int add(int x, int y) |
myfunc.h
:
1 | int add(int x,int y); |
然后使用gcc -c ***
各自生成可执行文件,接下来我们将两个中间文件进行链接:
使用gcc -o test test.o myfunc.o -lm
进行链接,然后成功执行:
tips:
如果遇到下面这种情况:
是因为本文件夹中查找不到,将头文件中的#include <myfunc.h>改成#include “myfunc.h”即可~
总结:
- gcc -c <filename1.c>
- gcc -c <filename2.c> …
- gcc -0
<filename.o> <filename2.o> …… -l …..
第四种编译方式(makefile)
利用makefile文件来编译程序
1 | test:test.o myfunc.o |
执行
tips:
采用倒叙的方式书写
gcc,rm
等命令前加的是TAB (注意不要用空格代替制表符!)
makefile文件格式总结:
<模块名>:<生成所需资源文件>
gdb调试方法
不能直接使用,需要在编译时加入调试方法
采用的指令是 gcc -g
例如:输入gcc -g test.c myfunc.c -o test -lm
也可以正常生成,但是会发现可执行文件容量比较大。
输入gdb test
进入调试,界面如下:
查看代码:
list (查看10行的内容)
list 10 (以第10行为中心上下共10行的内容)
list 6,12 (列出6到12行的内容)
输入run
可以使得程序在调试时运行
断点设置:
设置断点 break 行数
清除断点
采用
info break
查看断点信息输入
delete breakpoint <Num>
即可删除对应编号的断点。print data
即可查看当前赋的值单步运行
① step进入函数体的单步执行
② next 不进入函数体的单步执行
多步执行
step <步数>
next <步数>
gdb总结:
生成: gcc -g <源文件> -o <执行文件> -l<库>
进入调试 gdb
list 显示十条语句
list n 以n为中心,显示十条语句
list m,n 显示从m到n的语句
break <行号> 设断点
info break 显示断点信息
delete breakpoint <编号>
enable/disable breakpoint <编号> 启用/禁用 断点
run 执行到断点
step进入函数体的单步执行
next 不进入函数体的单步执行
print <变量> 查看变量信息