我们在windows环境和macos环境里都有功能强大的集成开发环境(IDE)供我们使用 ,但是在Linux中我们如何编译运行我们的代码呢?这里就需要使用gcc / g++ 了。
在学习使用gcc之前,我们需要了解代码的编译过程(可以看文章: 编译与链接):
了解了上述背景知识,我们需要通过gcc来帮助我们实现这四个步骤,让代码可以成功运行。
gcc [选项] 要编译的文件 [选项] [目标文件]
这一步指令就可以帮助我们得到可执行程序。效果如下:
我们接下来再来看具体每一步的操作如何实现
预处理指令:
gcc -E 要预处理的文件 [选项] [目标文件]
一般我们得到的预处理文件使用.i
后缀
我们可以验证一下预处理是不是完成去注释等操作:
可以看到经过预处理之后,我们的代码变成了近千行,这就是对头文件进行的引用展开(去注释后),展开宏定义的效果。
先引入一个问题,一个产品的不同版本(个人版 社区版 专业版)需要维护几个文件??? 答案是: 一个 条件编译就是实现这个的重要方法;
通过条件编译我们就实现了对于一个代码的不同版本实现!!!
编译指令:
gcc -S 要编译的文件 [选项] [目标文件]
一般我们得到的编译文件使用.s
后缀
我们来看看是不是可以成功转换为汇编语言:
可以看到刚才的近千行代码成为了使用汇编语言的文件。
汇编指令:
gcc -c 要汇编的文件 [选项] [目标文件]
一般我们得到的二进制文件使用.o
后缀
我们来看看是不是可以成功转换成二进制文件:
现在使用 vim 打开后是乱码,大致可以理解是已经转换成二进制了。
链接指令:
gcc 要链接的文件 [选项] [目标文件]
一般我们得到的可执行文件使用.exe
后缀
我们来执行这一步看看效果:
成功执行!!!
我们的代码中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢???
答案是:
系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函 数“printf”了,而这也就是链接的作用
这里的库又分为动态库 和 静态库
gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件
我们看看使用动态库和静态库的区别:
使用静态库的可执行文件比使用动态库的文件大了近100倍 这就是因为静态库把库加到了可执行文件里。让文件的可移植性大大加强!当然所占内存也打了不少。