👻内容专栏: Linux操作系统基础
🐨本文概括: 预处理、编译、汇编、链接、动静态库、gcc选项等。
🐼本文作者: 阿四啊
🐸发布时间:2023.9.13
背景知识
- 预处理(进行宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 连接(生成可执行文件或库文件)
如何用gcc进行编译
格式:gcc [选项] 要编译的文件 [选项] [目标文件]
📌gcc命令记忆技巧:ESc
(键盘左上角键) + iso
(镜像文件后缀)
预处理(进行宏替换)
- 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
- 预处理指令是以#号开头的代码行。
- 实例:
gcc –E hello.c –o hello.i
- 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
- 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序
编译(生成汇编)
- 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
- 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
- 实例:
gcc –S hello.i –o hello.s
汇编(生成机器可识别代码)
- 汇编阶段是把编译阶段生成的“.s”文件转成目标文件
- 在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
- 实例:
gcc –c hello.s –o hello.o
链接(生成可执行文件或库文件)
- 在成功编译之后,就进入了链接阶段。
- 实例:
gcc hello.o –o hello
函数库
- 在这里涉及到一个重要的概念叫做函数库。
- 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?
- 最后的答案是:系统把这些函数实现都被做到名为
libc.so.6
的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6
库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。[Asi@localhost ~]$ ldd mybinlinux-vdso.so.1 => (0x00007fff7e5e9000)libc.so.6 => /lib64/libc.so.6 (0x00007f0c99260000)/lib64/ld-linux-x86-64.so.2 (0x00007f0c9962d000)
函数库一般分为静态库和动态库两种
-
动态库
(动态链接):是C/C++或者其他第三方提供的所有方法的集合,被所有程序以链接的方式关联起来。所谓的动态链接,其实是将要链接的库中的函数地址拷贝到我们可执行程序的特定位置。优点:形成的可执行程序小,有利于节省系统的开销。
缺点:强依赖性,动态库没了,那么,所有与动态库关联的程序都无法运行。 -
静态库
(静态链接):是C/C++或者其他第三方提供的所有方法的集合,被所有程序以拷贝的方式,将需要的代码,拷贝到自己的可执行程序中。优点:可以独立运行,无需额外的库文件。
缺点:可执行文件大,导致磁盘空间的浪费。
⚠️注:默认情况下,XShell中是没有安装静态库的,只有动态库,如果要安装,执行以下命令:👇C语言静态库
[Asi@localhost ~]$ sudo yum install -y glibc-static
👇C++静态库
[Asi@localhost ~]$ sudo yum install -y libstdc++-static
-
演示:
创建一个test.c
文件,写入一段C语言代码。
将test.c
文件动态链接(gcc编译器默认情况下链接的是动态库)取名为test-d
[Asi@localhost ~]$ gcc test.c -o test-d
再次将
test.c
文件静态链接(需要添加-static选项)取名为test-s
[Asi@localhost ~]$ gcc test.c -o test-s -static
对比发现,动态链接后生成的可执行文件的大小与静态链接后生成的可执行文件大小相差了近百倍,所以gcc下为什么默认情况下生成动态链接库。
[Asi@localhost ~]$ ll total 876 -rw-rw-r-- 1 Asi Asi 127 Sep 12 15:40 test.c -rwxrwxr-x 1 Asi Asi 8480 Sep 13 15:47 test-d -rwxrwxr-x 1 Asi Asi 861216 Sep 13 16:22 test-s
gcc选项
- -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
- -S 编译到汇编语言不进行汇编和链接
- -c 编译到目标代码
- -o 文件输出到 文件
- -static 此选项对生成的文件采用静态链接
- -g 生成调试信息。GNU 调试器可利用该信息。
- -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
- -O0 不进行优化
- -O1 启用基本优化级别
- -O2 启用更多的优化
- -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
- -w 不生成任何警告信息。
- -Wall 生成所有警告信息