C++编译

来源:互联网 发布:计算机模块考试软件 编辑:程序博客网 时间:2024/06/09 15:09

一个cpp文件执行g++命令编译得到out文件可以分解为4个步骤:

  • 预处理(Prepressing)
  • 编译(Compilation)
  • 汇编(Assembly)
  • 链接(Linking)

编译与链接

预处理

g++ -E test.cpp -o helloworld.i

-E 表示只执行到预编译,直接输出预编译结果

预编译的主要处理以#开始的预编译指令,规则如下:

  • 将所有的#define删除,并且展开所有的宏定义
  • 处理所有条件预编译指令,比如#if/#ifdef/#elif/#else/#endif
  • 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置
  • 过滤所有的注释”//”,”/**/”中内容
  • 添加行号和文件名标识
  • 保留所有的#pragma编译器指令

当无法判断宏定义是否正确或头文件包含是否正确时,可以查看预处理后的文件来确定问题。

编译

编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析以及优化后产生相应的汇编代码文件。

g++ -S helloworld.i -o helloworld.s

链接

每个源代码模块独立地编译,然后按照要将它们”组装”起来,这个组装模块的过程就是链接。链接的主要内容就是把各个模块之间相互引用的部分都处理好,使得各个模块之间能够正确的衔接。

链接的过程主要包括了地址和空间分配、符号决议和重定位等这些步骤。

每个目标文件除了拥有自己的数据和二进制代码外,还提供了3个表:

  • 未解决符号表:在该编译单元里引用,但未定义的符号以及出现的地址
  • 导出符号表:本单元定义,并且愿意提供给其他单元使用的符号及其地址
  • 地址重定向表:本单元所有对自身地址的引用的记录

编译器将extern声明的变量置入未解决符号表,属于外部链接;static声明的变量不在这3个表内,属于内部链接;普通变化及其函数被置入导出符号表。

静态链接

对函数库的链接是放在编译时期完成的,所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。静态库的通常为libxxx.a的形式。

动态链接

在程序运行时期载入函数库,这样的函数库是动态链接库。通常为libxxx.so的形式。

静态链接库与动态链接库特点

  • 动态链接库有利于进程间资源分享
  • 动态库将一些程序升级变得简单
  • 静态库速度比动态链接库快