1.3.2.2 编译# 通过添加参数 -S 将 test.i 转换为汇编文件 test.s(默认生成 .s 文件)$ gcc -S test.i$ gcc -S test.i -o test.s # 写法二1.3.2.3 汇编# 通过汇编得到二进制文件 test.o(默认生成 .o 文件,object)$ gcc -c test.s$ gcc -c test.s -o test.o # 写法二1.3.2.4 链接# 通过链接得到可执行文件 test$ gcc test.o -o test在成功生成 test.o 文件后,就进入了链接阶段 。在这里涉及到一个重要的概念:函数库 。
在 test.c 的代码中,我们通过print()函数打印 Hello World 语句;但是在这段程序中并没有定义 printf 的函数实现,且在预编译中包含进去的「stdio.h」中也只有该函数的声明extern int printf (const char *__restrict __format, ...);,而没有定义函数的实现,那么是在哪里实现的呢?
答案就是:系统把这些函数实现都做到了名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径 /usr/lib64 下进行查找,也就是链接到 libc.so.6 库函数中去,这样就有函数 printf 的实现了,而这也就是链接的作用 。

文章插图
而函数库一般分为静态库和动态库两种:
- 静态库是指在编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不需要库文件了 。在 Linux 中静态库一般以 .a 作为后缀 。
- 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时链接文件加载库,这样就可以节省系统的开销 。在 Linux 中动态库一般以 .so 作为后缀 。
有关动态库和静态库的详细介绍,将在下文进行具体讲解 。
1.3.2.5 总结最后,通过一张图来总结一下上述流程:

文章插图
在 Linux 下使用 GCC 编译器编译单个文件十分简单,直接使用1.4 GCC 常用参数下面的表格中列出了一些常用的 gcc 参数,这些参数在 gcc 命令中没有位置要求,只需要编译程序的时候将需要的参数指定出来即可 。$ gcc test.c(test.c 为要编译的 C 语言的源文件),GCC 会自动生成文件名为 a.out 的可执行文件(也可以通过参数 -o 指定生成的文件名);也就是通过一个简单的命令就可以将上边提到的 4 个步骤全部执行完毕了;但是如果想要单步执行也是没问题的 。
gcc 编译选项解释说明-E预处理,主要是进行宏展开等步骤,生成 test.i-S编译指定的源文件,但是不进行汇编,生成 test.s-c编译、汇编源文件,但是不进行链接,生成 test.o-o指定链接的文件名及路径-g在编译的时候,生成调试信息,该程序可以被调试器调试-D在程序编译的时候,指定一个宏-std指定 C 方言,如 -std=c99 。gcc 默认的方言是 GNU C-l在程序编译的时候,指定使用的库(库的名字一定要掐头去尾,如 libtest.so 变为 test)-L在程序编译的时候,指定使用的库的路径-fpic生成与位置无关的代码-shared生成共享目标文件,通常用在建立动态库时1.4.1 指定一个宏(-D)在程序中我们可以通过使用
#define定义一个宏,也可以通过宏控制某段代码是否能够被执行 。#include <stdio.h>int main(){int num = 60;printf("num = %d\n", num);#ifdef DEBUGprintf("定义了 DEBUG 宏, num++\n");num++;#elseprintf("未定义 DEBUG 宏, num--\n");num--;#endifprintf("num = %d\n", num);return 0;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- java中GC的日志认识详解
- 2023年摩羯座财运1月运程详解如何提高
- 我的世界指令附魔攻略(我的世界附魔1000级的指令)
- JUC中的AQS底层详细超详解
- 图文详解 微服务 Zipkin 链路追踪原理
- 电影谜一样的双眼剧情详解?
- 谍影重重4剧情详解?
- 西虹市首富剧情详解?
- 唐人街探案3剧情详解_唐人街探案3讲了什么剧情
- 2023年农历二月十八黄历宜忌详解
