整理C/C++程序编译流程

一、编译流程

1.预处理

2.编译

编译阶段后面会有文章进行详细解读

3.汇编

4.链接

二、编译阶段

1.编译阶段阶段分别是检查和各个文件组成整体,也会出现全局空间的函数多出定义。原因是头文件被释放到多个源文件中

tips:

1.标准CC++将编译过程

标准CC++将编译过程定义为9个阶段(PhasesofTranslation)

  • 字符映射(CharacterMapping)

  文件中的物理源字符被映射到源字符集中,其中包括三字符运算符的替换、控制字符(行尾的回车换行)的替换。许多非美式键盘不支持基本源字符集中的一些字符,文件中可用三字符来代替这些基本源字符,以??为前导。但如果所用键盘是美式键盘,有些编译器可能不对三字符进行查找和替换,需要增加-trigraphs编译参数。在C++程序中,任何不在基本源字符集中的字符都被它的通用字符名替换。

  • 行合并(LineSplicing)

  以反斜杠/结束的行和它接下来的行合并。

  • 标记化(Tokenization)

  每一条注释被一个单独的空字符所替换。C++双字符运算符被识别为标记(为了开发可读性更强的程序,C++为非ASCII码开发者定义了一套双字符运算符集和新的保留字集)。源代码被分析成预处理标记。

  • 预处理(Preprocessing)

  调用预处理指令并扩展宏。使用#include指令包含的文件,重复步骤14。上述四个阶段统称为预处理阶段。

  • 字符集映射(Character-setMapping)

  源字符集成员、转义序列被转换成等价的执行字符集成员。例如:'/a'ASCII环境下会被转换成值为一个字节,值为7

  • 字符串连接(StringConcatenation)

  相邻的字符串被连接。例如:"""hahaha""huohuohuo"将成为"hahahahuohuohuo"

  • 翻译(Translation)

  进行语法和语义分析编译,并翻译成目标代码。

  • 处理模板
       处理模板实例。
  • 连接(Linkage)
  解决外部引用的问题,准备好程序映像以便执行。

2.如何避免出现全局空间的函数多出定义?

也就是说头文件被多个cpp文件include的时候,避免出现函数多定义的问题。解决方案有两个,一是对头文件中出现的内容进行限制;二是通过 "#define" 配合条件编译解决。
1)头文件是什么
2)解决方案
  • 对头文件中出现的内容进行限制

  • 通过"#define"配合条件编译解决

三、linux相关指令gcc/g++

1.编译阶段命令

阶段选项作用命令
预处理-EGCC的选项-E使GCC在进行完预处理后即停止
$ gcc -E test.c -o test.i

编译-SGCC的选项-S使GCC在执行完编译后停止,生成汇编程序
$ gcc -S test.i -o test.s

汇编-cGCC的选项-c使GCC在执行完汇编后停止,生成目标文件
$ gcc -c test.s -o test.o

2.链接阶段命令

上图中的链接库分为动态链接库和静态链接库,即.a和.so

静态链接和动态链接的区别?

静态库链接和动态库链接的查找路径

静态库链接库.a查找路径,在Linux系统中,gcc编译链接时的动态库搜索路径的顺序通常为:

  • 首先从gcc命令的参数-L指定的路径寻找;
  • 再从环境变量LIBRARY_PATH指定的路径寻址;
  • 再从默认路径/lib、/usr/lib、/usr/local/lib寻找;

动态库链接.so查找路径,在Linux系统中,执行二进制文件时的动态库搜索路径的顺序通常为:

  • 将动态库添加到系统默认的搜索路径下,如/lib、/usr/lib
  • 设置临时动态库路径的环境变量,这种方法设置的是临时的,系统重启之后就没了
$ export LD_LIBRARY_PATH=./

# 取消设置

$ export LD_LIBRARY_PATH=
  • /etc/ld.so.cache中缓存了动态库路径,可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变
  • 编译链接添加-WL,-rpath命令选项,将运行时动态库的搜索路径记录在可执行程序中
  • 再从默认路径/lib、/usr/lib寻找。
阶段选项作用命令
链接- 编译链接一起,生成a.out
$ g++ test.cc 
-I指定文件查找目录

-include file

-I file

指定包含的文件

$ g++ test.cpp -include ../include/test.h
-L指定链接库(静态库和动态库),动态库和静态库名字一致时,优先使用动态库

-L library 指定路径

-llibrary 指定特定文件

$ g++ -o test.c -L. -ltest
# 使用静态库 -L.表示静态库位于当前目录下,test自动加上lib组成静态库名称libtest.a

-fPIC生成动态库
$ g++ -fPIC -shared test.cpp -o libtest.so
# 生成动态库libtest.so, 

# -fPIC生成的动态库时位置无关的。多个进程引用同一个PIC动态库时,可以共享内存, 不加fPIC,则加载so文# 件时,需要对代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成每个使用这个.so文件# # 代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于这个.so文件代码段和数# 据段内存映射的位置。

# -shared将尽量使用动态库,为默认选项

附加项

阶段选项作用命令
-g 在编译的时候,产生调试信息,程序运行时可以dbg调试
$ g++ -g test.cc 
  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值