【Linux编译器】
前言
打怪升级第:22天 |
---|
一、gcc、g++
背景知识:
gcc和g++都是Linux中的编译器,其中gcc只可以编译C语言文件,g++可以编译c++文件,当然也可以编译C语言文件(c++兼容C语言嘛)。
由于两者的操作选项基本一样,这里我们就以gcc为例来深入了解它们。
编译的过程:
- 预处理(进行宏替换,头文件包含等操作)
- 编译(生成汇编等)
- 汇编(生成机器可以识别的代码等)
- 链接(生成可执行文件、库文件等)
语法:gcc 选项 .c文件 选项 目标文件
注意:下方是对gcc编译器的各个步骤的拆分介绍,如果只需要知道gcc的使用方法,下方两句指令就足够了:
- gcc test.c
- ./a.out
(一)预处理
预处理时的操作:
- 宏替换,将宏定义的内容替换到对应位置;
- 头文件展开,将包含的头文件中的内容拷贝到文件中;
- 条件编译,#if #elif #endif;
- 去注释,有注释的位置换成空行。
语法:gcc -E test.c -o test.i
功能:从现在开始对文件进行翻译,预处理结束后停止;
-o test.i 是将预处理后的文件信息存储到test.i文件中,(文件名可以随便起,但是很多程序员都会使用 .i 后缀),否则会默认输出到控制台。
(二)编译
编译时的操作:
- 检查文件代码的规范性,语法的正确性;
- 将文件编译成汇编代码(默认保存在文件:test.s)。
语法:gcc -S test.c / gcc -S test.i
功能:从现在开始对文件进行翻译,编译结束后停止;
(三)汇编
汇编时的操作:
- 将汇编代码转换为机器可以识别的二进制代码(默认保存在文件:test.o)。
语法:gcc -c test.c / gcc -c test.s / gcc -c test.i (从 test.XXX开始)
功能:从现在开始对文件进行翻译,汇编结束后停止;
补充:
- 由于汇编结束后生成的是二进制代码,我们使用文本模式查看到的会是乱码。
- 前三步都是对我们自己写的文件进行翻译,将它翻译为二进制文件。
- 头文件不需要进行翻译,因为在预处理阶段已经将需要的头文件拷贝过来了。
- 汇编生成的obj文件不可执行,有几个.c文件就会生成几个obj文件。
(四)链接
链接时的操作:
- 将我们生成的obj文件与库文件进行链接,生成可执行文件(默认文件名为:a.out)。
语法:gcc test.c / … …
功能:从现在开始对文件进行翻译,生成可执行文件。
(五)补充:
1.动态库、静态库
动态库和静态库:我们在进行预处理、编译以及汇编时都是对我们自己写的文件进行翻译,在汇编结束后生成的obj目标文件是不可执行的,
直到链接阶段与库文件链接到一起之后才能生成exe可执行文件。 而链接阶段所链接的库分为两种:静态库和动态库(重要)。
静态库:在编译链接阶段,将库文件中的代码全部拷贝到目标文件中,因此文件会比较大,但是之后就不再需要库文件了;
静态库格式一般为:前缀lib + XXX +后缀 .a动态库:与静态库相反,在编译链接阶段只是将需要用到的库的地址放到目标文件中,在程序执行时由运行时链接加载库,这样可以减小内存的开销;
动态库格式一般为:前缀lib +XXX +后缀 .so
我们在日常编写程序时基本上都会用到库函数,系统把这些函数实现都放到了libc.so.6的库函数中去了,在没有特别指定时,gcc 会到
系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6
库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。
在gcc编译的时候默认链接的是动态库,如果想要链接静态库,可以使用指令:gcc test.c -static
2.ldd指令
语法:ldd file
功能:列出文件动态库依存关系
参考文章:ldd命令简介
(六)其他选项
二、gdb
gdb:对debug版本进行调试
热键:回车,回车键会记录上一个执行的指令。