首先我们需要知道有两种编程语言
编译型语言:要求必须提前将所有源代码一次性转换成二进制指令,也就是生成一个可执行程序,例如C、C++、go语言、汇编语言等,使用的转换工具称为编译器。
解释型语言:一边执行一边转换,需要哪些源代码就转换哪些源代码,不会生成可执行程序,相当于翻译一句,然后执行一句,比如 Python、Java、PHP、Shell、Ruby、MATLAB 等,使用的转换工具称为解释器。
c语言是编译型语言,所以源代码需要经过一系列步骤转换成可执行程序才能执行,在Linux系统中就使用gcc命令来实现转换
在Linux系统中有以下后缀表示的文件类型
.c 源代码文件。
.i 已经预处理的C源代码文件。
.s 汇编语言源代码文件。
.o 编译后的目标文件。
.ii 已经预处理的C++源代码文件。
.h 程序所包含的头文件。
.a 静态链接库文件,格式为lib库名.a
.so 动态链接库文件,格式为lib库名.so,一定是以lib开头
源代码转换成可执行程序通常需要以下几步
预处理:将源程序.c预处理,生成.i文件。
编译:将预处理后的.i文件编译成为汇编语言,生成 .s文件。
汇编:将汇编语言文件经过汇编,生成目标文件.o文件。
链接:将.o目标文件链接起来生成一个可执行程序文件,可分为静态链接和动态链接
静态链接:链接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,一旦链接成功就可独立运行,生成的可执行文件不再需要任何静态库文件的支持就可以独立运行。缺点是如果所使用的静态库发生更新改变,就需要必须重新编译。
动态链接:不会直接将该函数的代码拷贝到文件中,而是将函数的位置信息记录到文件中,然后生成可执行文件。这样生成的可执行文件是无法独立运行的,但是可执行文件中记录了所需功能函数的位置信息,所以也可以成功运行。如果该动态链接库不存在了该可执行文件就无法运行。动态库的代码只有程序执行的时候才会加入到可执行文件,优点就是用户更新了动态库不需要重新编译,缺点是可移植性差,无法独立运行,必须借助相应的库文件。
gcc命令选项
-E :预处理
-S :预编译
-c :汇编
-o :指定文件名
-Idir:将dir加入到头文件的搜索目录中,默认的搜索目录是/usr/include,如果编译的时候需要的头文件不在/usr/include中,就需要使用-Idir添加搜索目录
-Ldir:将dir加入到库文件的搜索目录中,默认的搜索目录是/usr/lib,如果链接的时候需要的库函数文件不在/usr/lib中,就需要使用-Ldir添加搜索目录
-l:指定库函数的名字
各步骤使用的命令,源文件为test.c
1、预处理:gcc -E test.c -o test.i只执行预处理操作得到预编译文件。
2、编译:gcc -S test.i -o test.s将预编译文件编译输出汇编文件。
3、汇编,gcc -c test.s -o test.o
4、链接,将目标文件与所需的附加目标文件(静态链接库和动态链接库、C标准输入输出库)连接起来,最终生成可执行文件test:gcc test.o -o test
通常可以只执行以下两步:
.c文件执行gcc -c编译成.o目标文件,然后执行gcc -o链接成可执行程序
编译命令:gcc -c 文件名.c
链接命令:gcc -o 文件名.o 指定可执行文件名
也可以编译和链接一起:gcc -o 文件名.c 指定可执行文件名
执行命令:./指定可执行文件名
例如hello.c文件
gcc -c hello.c //将hello.c编译成hello.o目标文件
gcc hello -o hello.o //将hello.o目标文件链接成hello可执行程序
./hello.out //然后运行该可执行程序
-o表示指定可执行文件的名字,如果只执行gcc 文件名.c,将会默认生成a.out可执行文件
如果hello.c文件使用了自己编写的头文件,且该头文件不在/usr/include默认搜索路径中,而是在/usr/local/pow/include,还使用了自己编写的函数库,且该函数不在/usr/lib默认搜索路径中,而是在/usr/local/pow/lib,该函数库为libhello.so,就需要使用-I选项和-L选项指定头文件和库函数的位置,用-l指定是哪个库函数,这里要注意使用-l选项时库函数前面的lib和.so要去掉,例如指定libhello.so库函数就是-lhello
gcc -c hello.c -I/usr/local/pow/include
//编译,增加头文件搜索目录/usr/local/pow/include
gcc -o hello hello.o -L/usr/local/pow/lib -lhello
//链接,增加库函数文件搜索目录/usr/local/pow/lib和指定库函数
也可以直接-I,-L,-l三个选项一步到位
gcc -o hello hello.o -L/usr/local/pow/lib -I/usr/local/pow/include -lhello
如果头文件和库函数名都在默认搜索路径中,则只需要指定库函数名,如源代码使用了内置的数学函数库math需要使用-lm链接,m是math库的缩写