1.误区:gcc只能编译C源代码,g++只能编译C++源代码
解析:其实gcc和g++都可以编译c/c++源代码,只是细节不同,后缀名为.c的源文件,gcc将其当作C程序,而g++则当作c++程序来处理;后缀名为.cpp的源文件,gcc和g++都会当作C++程序来处理。编译阶段,g++会调用gcc来进行编译,但由于gcc不能链接程序所使用的库,所以需要通过g++来链接库文件,即在编译阶段都是使用gcc来进行编译,但当进入链接阶段的时候,由于gcc无法自动链接库文件,要想使用gcc链接库文件必须使用选项-lstdc++,而g++则会自动链接,为了方便起见,对于.cpp的文件就直接使用g++来进行编译和链接。
2.一个c/c++程序是经过以下几个阶段完成编译链接生成可执行文件的
(1)预处理阶段:一段程序中通常会包括宏定义和头文件包含,预处理阶段就是对这两者进行处理,同时包含了语法检查,该阶段命令为gcc -E hello.c -o hello.i,生成一个hello.i文件,hello.i文件特别大,是因为将头文件进行了替换添加到了程序中
(2)生成汇编文件:对生成的hello.i预处理文件进行汇编生成汇编文件hello.s,该阶段命令为gcc -S hello.i -o hello.s
(3)由汇编文件生成目标文件:对汇编文件hello.s进行进一步处理,使每个源程序生成一个目标文件hello.o,该阶段命令为gcc -c hello.s -o hello.o
(4)链接目标文件和库函数文件,生成可执行文件:在链接阶段,将目标文件和库文件链接起来,生成最终的可执行文件,该阶段命令为gcc hello.o -o hello
(5)运行可执行文件hello
3.静态库
(1)什么是库:库是写好的现有的可以复用的代码,库有两种:静态库(.a、.lib)和动态库(.so、.dll)
(2)静态库:之所以称为静态库,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,因此对应的链接方式称为静态链接。其实静态库可以简单的看成是一组目标文件的集合,即许多目标文件通过压缩打包后形成的一个文件;
(3)静态库的特点:静态库对函数的链接是放在编译时期完成的;程序在运行时与函数库再无瓜葛,移植方便;空间和资源消耗比较大,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件
(4)Linux下静态库命名规范:必须是"lib[your_library_name].a",lib为前缀,中间是静态库名,扩展名为.a
(5)创建静态库:首先,将源文件编译为目标文件,g++ -c hello.cpp;然后通过ar工具将目标文件打包成静态库文件,ar -crv libhello.a hello.o,生成静态库libhello.a。注意:大一点的项目就需要编写makefile文件来生成静态库了,毕竟输入命令比较麻烦
(6)使用静态库:Linux下使用静态库,只需要在编译的时候,指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,使用-l选项),如:g++ test.cpp -L"path" -lhello
4.动态库
(1)动态库的产生是由于静态库会造成大量空间浪费并且静态库对于程序的更新重新部署发布会很麻烦,只要静态库发生变化,程序就需要重新编译再发布。动态库在程序编译时并不会被链接到代码中,而是在程序运行时才被载入。不同的程序如果调用相同的库,那么内存中只需要有一份实例即可。
(2)动态库特点:库函数在程序运行时才被载入;可以实现进程间的资源共享;程序升级更新简单,只需要更新库文件无需重新编译程序;
(3)创建动态库:Linux下与创建静态库不同的是,不需要打包工具,直接使用编译器即可创建动态库
(4)动态库的命名规则:动态链接库的名字形式为libxxxx.so,前缀是lib,后缀为.so
(5)创建动态库:首先生成目标文件,g++ -fPIC -c hello.cpp(-fPIC创建于地址无关的编译程序,是为了能够在多个程序间共享);然后生成动态库,此时要加连接器选项-shared,g++ -shared -o libhello.so hello.o;也可以合并为一句命令:g++ -fPIC -shared -o libhello.so hello.cpp
(6)使用动态库的方式和使用静态库的方式是一样的
总结:动态库和静态库的最大不同就在于被载入的时间不同,静态库在程序编译时会被链接到代码中,程序运行时不再需要静态库,因此体积较大。而动态库则是在程序运行时才被载入,因此在程序运行时还需要动态库存在,因此体积较小。