C++编译器 GCC G++ 使用
gcc和g++都是GNU(组织)的一个编译器。
但两者有一些区别:后缀为.c的文件gcc把它当做c程序,g++当做c++程序。后缀为c++的两者都当做c++程序。对于cpp程序,无论gcc或者是g++编译阶段都是相同的,都是用的gcc进行编译,但是在链接阶段gcc不能自动和c++程序使用的库连接,如果使用的话,形如下: gcc helloworld.cpp -lstdc++ -o helloworld
所以我们通常用g++来进行连接(g++会自动连接c++常用库),所以为了使用方便对于cpp程序干脆编译链接统统都使用g++,这样就给人一种错觉,好像cpp只能用g++编译。
Gcc编译处理过程是什么呢?
下面以helloworld程序为例去进行解释过程:
其中hello.c的内容如下:
#include<stdio.h>
int main()
{
printf("hello world\n");
}
第一步:预处理
预处理阶段过程如下,预处理阶段是进行处理代码中的宏和include指令,并作语法检查。这一过程的命令为:# gcc -E hello.c -o hello.i 执行这一部生成了一个hello.i文件,如下:
可以看到由于进行了预处理,将include内部的文件进行了替换,预处理后的结果文件显得特别大,所以在以后的程序中,没有用到的头文件最好不要引入,这样会降低处理时间和空间。
第二步:汇编程序生成汇编码
这一步是将预处理文件进行汇编,生成汇编程序,命令如下:
可以看出生成的汇编程序为59行。
第三步:由汇编程序转换为中间目标文件
这一步是将汇编的代码进一步进行处理,每一个源程序都会生成相应的目标文件,是以.o为扩展名的文件。命令如下:
第四步:连接目标文件,生成可执行程序
这一阶段被称为链接阶段,这一阶段完成的是将目标文件进行连接生成相应的最终目标文件(可执行文件或静态库或动态库)
好了,这样例子中的可执行文件就生成了hello,运行一下为:
如何使用g++编译动态库\静态库?如何使用g++连接非标准库和应用程序?
什么是库呢?简单的说库就是一组已经写好了的函数和变量、是经过编译了的代码,为了提高开发的效率和运行的效率而设计的。库可以分为静态库和动态库(共享库)两类,在linux系统中静态库的扩展名为.a,动态库的扩展名是.so。
静态库是在每个程序进行链接的时候将库在目标程序中进行一次拷贝,当目标程序生成的时候,程序可以脱离库文件单独运行,换言之原来的文件即使删除程序还是会正常工作。
共享库可以被多个应用程序共享,实在程序运行的时候进行动态的加载,因此对于每个应用程序来说,即使不再使用某个共享库,也不应该将其删除,因为其他的引用程序可能需要这个库。
1. 如何生成库
下面演示如何生成静态库和动态库:
生成静态库的过程是先将每个每个原文件进行编译生成中间目标文件,然后利用打包程序,将程序进行一次打包,最后生成静态库文件。以下面的例子说明问题:
目录结构为
包括3个文件,其中hello.c是用来生成静态库的源文件,hello.h是其头文件,test.c是其测试程序,用来测试库生成是否正确,在这个例子中我们会将hello.c生成libhello.a,然后用test.cpp进行连接,最后生成hello的可执行文件。
首先生成库文件,
然后通过链接静态库文件,将test.c和libhello.a生成相应的应用程序testhello
在这个例子中,我们删除静态库后,程序依然正常运行。
下面通过生成动态库连接成为应用程序,生成动态库的命令是
gcc -shared -fPIC hello.c -o libhello.so这样就生成了动态库
在把so所在的路径在环境变量里添加上,注意应该添加到LD_LIBRARY_PATH中,另外还要运行命令ldconfig,此命令在/sbin/目录下。这样就能正常运行了。下面是测试:
如果删除之后,在运行就会:
从上面可知,如果在小的项目中使用gcc还是比较方便的,如果再大的工程中,我们必须记住gcc命令,如果想让程序做移植的话,必须还得充足的文档才能管理大项目。下面提供一种解决方法,通过makefile来解决这些问题,当你移植你的程序时只需要做简单的操作,就能成功生成相应的二进制文件,从而简化了大项目的管理等问题。
GCC编译器的选项解读
1. 基本选项
-E是只进行预处理选项,不进行编译、汇编、以及连接
-S 编译后停止,不进行会变和连接
-c编译或会汇编文件,但不进行连接
-o file 指定输出文件名
2. 警告选项
-Wall 启用所有警告信息
-Werror 在发生警告时取消编译操作,即将警报看作是错误
-w 禁用所有警告信息
3. 优化选项
-O0:不进行优化处理
-O或-O1:进行基本的优化,这些优化在大所属情况下都会使程序执行的更快
-O2:除了完成-O1级别的优化外,还需要一些其他的调整工作,如处理器指令调度等,只是GNU发布软件的默认优化
-O3:除了完成-O2级别的优化外,还进行循环的展开(这往往会提高执行速度)以及其他的一些预处理器相关的优化工作。
-Os:生成最小的可执行文件,主要用在嵌入式领域。
4. 连接器选项
-Idirectory 向GCC的头文件搜索路径中添加新的目录
-Ldirectory 向GCC的库文件搜索路径中添加一个行的目录
-llibrary 提示连接程序在创建可执行文件时包含指定的库文件