
c++只是一个文本可以理解为txt,编译器将文本转换为实际应用程序的方法
从文本变为二进制文件分为两步:编译、链接
如果学过java可以更好理解这个区别:在java中创建一个类,需要类名文件名一致,并且package路径要对;而c++不是,他只是一个文件,只需要告诉编译器这个文件是什么类型即可,是后缀cpp的或者txt的或者自定义的,然后告诉编译器这一类文件应该怎么处理就可以了
编译将所有的文本文件转换为目标文件的一种中间格式(obj)
生成obj文件做的几件事:
1.预处理代码,所有预处理语句都会先处理
会识别#后的预处理语句,
#include 会把包含的文件内容复制到标记的位置(就是直接复制文本)
#define 会把文件中所有和define名字一样的进行文本替换
#if 和#endif 会根据if后的条件进行判断是否预编译这两个标记之间的代码、
做个实验:
EndBrace.h文件:是的,只有一个花括号
}
math.cpp文件
#if 1
#define INTEGER heihei
INTEGER Multiply(int a,int b) {
INTEGER result = a * b;
return result;
#include "EndBrace.h"
#endif
接下来要改一个配置:为了一会能看到预处理后的代码
上面的准备工作做完以后就可以切换到math.cpp文件然后进行编译(Ctrl+F7)然后会生成一个math.i的文件;也可以注意到如果对整个项目进行编译的话,每个cpp文件都会生成一个对应的 obj文件。
我们打开这个文件
可以看到
1. #define INTEGER heihei 语句将所有INTEGER替换成了heihei(你想写啥都行,只是测试预编译用)
2.然后#include "EndBrace.h"把文件中的花括号复制了进来
3.如果#if后面是0 ,那么这段代码就不会被预编译了
上面预编译就结束了,记得把配置改回去,因为预处理到文件如果是yes,那么就不会生成obj文件
还有定义的全局变量改成能识别的 int,总之上面测试的代码只能通过预编译,因为heihei这个东西所以无法运行,可以改成int。
有没有发现main.obj很大几十kb,那是因为把iostream复制进去了
编译阶段首先还需要改下配置,因为obj是机器码,看不懂,我们需要看编译后的文件,所以改成下面配置,虽然我还是看不懂但至少有英文单词了
接下来一样滴Ctrl+F7 然后打开math.asm 文件,这个就是汇编语言啦,不研究了~电脑可以执行了
这个配置是一个优化配置两张图都要配置好不然会报错,选择最大速度,在次编译后你会发现文件内容会少很多,比如写了没用的代码也会被优化掉
不晓得为啥,日后更新
链接器把每个cpp文件生成的obj文件链接到一起,生成最后的exe可执行文件
上一阶段每个cpp文件生成的obj文件之间是没有任何交互的,链接器可以找到里面每个符号、函数对应的文件;当你按下Ctrl+F7时只进行了编译 *** 作,并没有进行链接 *** 作,F5才会构建整个项目执行完整的编译和链接 *** 作。
构建项目时有两类报错编译报错(以C开头的错误编码)和链接报错(LNK开头的错误编码)
方便理解举个例子:当我没有Log这个函数时(只要返回参数、函数名、入参有一个不一致就会找不到这个函数),就会报错LNK类型的
#include
void Log(const char* message);
int Multiply(int a,int b);
int main()
{
//std::cout << "Hello World!" << std::endl;
Log("Hello World!");
std::cout << Multiply(2,3);
std::cin.get();
}
这是因为链接器去查找这个函数了,我们可以补充这个函数,或者把这个注释掉
然后再看一个举例,即使注释掉了也会报错,虽然我没有调用这个代码,但是无法保证其他文件也没有调用,所以还会报错。那么告诉编译器只有这个文件调用这个方法,其他文件不会调用,如果代码被注释掉就不会链接了。
具体怎么告诉呢,加个static 静态就可以啦,这样就是这有这个文件才调佣,然后这个代码被注释掉了,链接器就不会去链接他了
在补充一下,如果两个函数一样,链接器不知道去链接哪个,也会报错
比如说在头文件里写了函数的定义,那么多个cpp引用头文件就会报错,因为include本质就是复制,导致每个cpp文件都复制了一模一样的函数,然后又对大家可见,两种方法解决,一个是方法添加static静态,只对自己可见,还有个方法添加inline就是当函数被调用时,会把函数定义直接替换到调用的地方。
当然啦,最好头文件只声明,然后在某个cpp中定义函数,这样即使被多次引用,也只是引用声明而已,寻找函数时只有一个cpp中定义了
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)