C++的编译和链接

前话

之前一直没能理解C++编译的逻辑,所以我一直很好奇,主程序的cpp文件里只注明了h头文件,而头文件跟cpp文件也并不要求一一对应,那么编译的时候,系统到底是如何从h文件往回找到相对应的函数源文件呢?
现在搞明白了,这里会用g++来做一个简单的逻辑梳理。

1、简介

g++是linux下最常用的编译工具,而在windows系统中,我们常直接使用vs等软件自带编译器进行编译,其实是一样的。

2、编译逻辑

#include
#include <iostream>
int main()
{
	 std::cout << "Hello World!" << std::endl;
	 std::cin.get();
	 //test
} 

通常情况下,我们编译这个程序是用这个指令

g++ test.cpp -o test

而从完整的逻辑上来讲,cpp文件的编译要经过四个阶段,分别是预处理(Preprocessing)、编译(Compilation)、汇编 (Assembly)和链接(Linking)。

2.1 预处理(Preprocessing)
g++ -E test.cpp -o test.i 

或者

g++ -E test.cpp

第一句指令会输出test.i文件,而第二句指令会直接将结果从窗口输出。通过输出结果我们就可以知道,预处理的其中一个作用,其实就是把头文件全部复制到test文件中来。

更准确的说,这一步会处理的是Preprocessing语句,包括include、defind、 if 等等,换而言之,我们为了方便而将程序拆成了各个不同的模块或者表达方式,而Preprocessing是反过来,将我们写成的这些程序重新生成一个完整的整体。

很多时候,程序中所包含的头文件中,又会包含新的头文件,特别是像iostream这种。所以,为了控制文件的大小,我们要尽量避免多余的头文件。

2.2 编译(Compilation)
g++ -S test.i -o test.s

这里是对生成的test.i文件编译,生成汇编代码。
所以虽然我们所写为c++,但实际上到机器运行时,还是先需要转化成汇编代码,才能进行下一步编译。

2.3 汇编 (Assembly)
g++ -c test.s -o test.o

将上一步生成的汇编代码进行编译,编译成机器代码。

2.4 链接(Linking)
g++ test.o -o test

负责将程序的目标文件与所需的所有附加的目标文件连接起来,这个时候只需要执行test文件,就可以实现代码 Hello,World。

2.5 error

在我们编写程序后进行一步到位的编译时,经常会出错,那么理解了编译的四个环节之后,我们就可以简单的去理解一些问题的原因。例如:
如果报错error CXXXX:那么就是编译(Compilation)出现了错误,一般是函数等未做声明
如果报错error LinkXXXX: 那么就是链接(Linking)出现了错误,一般是未找到函数的定义。

2.6 编译优化

编译优化并非一定会进行的,不过这里也顺便讲一下(例子
程序优化的内容包括:与程序 毫不相关的函数、多余的参数变量,消除多余步骤等。不同等级的优化程度不一样,一般O2就够了,O3以上有时候会出现编译时间长,编译失败等现象。

3、多文件编译

当我们需要同时进行多个cpp文件编译时。例如:

log.h
void Log(const char* msg);
log.cpp
#include <iostream>
void Log(const char* msg)
{
  std::cout << "Hello World!" << std::endl;
  //test
} 
test.cpp
#include <iostream>
#include 'log.h'
int main()
{
	Log("Hello World");
	std::cin.get();
}

那么这个时候,如果按照我们一开始的逻辑,使用函数时会遍历文件夹的所有cpp文件去找相对应的函数,那么我们的程序也应该是g++ test.cpp -o test。但根据我们梳理的四个步骤,可以发现实际上并不应该这么写,这么写的话,只有log.h跟test.cpp被纳入编译的初始文件。正确的编译指令应该这么写

g++ Log.cpp test.cpp -o test

而这样的话,我们就会迎来一个新的问题,如果一个项目文件很多,我们根本不可能像这样一个文件一个文件的去输入来编译,这样效率太慢了,所以就有了CMakeList的出现。
在各种项目文件夹中,我们都可以看见他,可以简单的理解成一个批量编译的脚本

4、最后

理解了编译的过程,那么还将有伴随而来的新的问题,都将在后面一一处理。
1、CMakeList的书写
2、如果多个cpp文件都用到同一个h文件,那么编译的时候不就会被重复编译?
3、函数的声明和定义?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值