01、IDE简介_编译链接

一、Hello World!

#include<iostream>		//预处理命令,寻找iostream这个文件,将该文件中的所有内容都复制粘贴到目前这个文件内

int main()
{
	std::cout << "Hello World" << std::endl;
    //等价于
    cout.
	std::cin.get();
}

任何以 # 开头的都是预处理指令,预处理发生在“真正”的编译之前

运算符 其实 就是函数

IDE简介

在这里插入图片描述

左边:配置,一系列的规则用于如何编译一个项目

右边:解决方案,是我们目前编译的木匾平台。x86–win31

项目属性页,决定我们的文件被如何编译的规则

在这里插入图片描述

编译与链接

  • 所有.cpp文件都会被编译,而头文件(head file)则不会。头文件是通过预处理器被include到cpp文件里

  • 每个cpp文件会被编译成一个object文件,用Windows编译器扩展名是.obj

  • 上图属性页里面可以看到链接器(linker),其作用就是把所有obj缝合成一个exe文件

  • 在vs里,可以用CTRL + F7 单独编译一个cpp文件
    在这里插入图片描述

  • 错误信息只看 输出窗口 ,错误列表不全面

在这里插入图片描述

编译

大致流程:

1、pre-process(预处理)代码,也就是所有的预处理语句会在那时被评估

2、预处理之后,进入tokenizing(标记解释)和parsing(解析)阶段,基本就是把这些C++文本处理成编译器能读和处理的语言。基本结果就是创建某种叫做abstract syntax tree(抽象语法树)的东西,也就是我们代码的表达,但是是以抽象语法树的形式

3、开始产生真正的CPU会执行的机器码

让编译器输出一个文档,里面包含所有这些预处理评估的结果(测试完之后关闭,因为不会生成 .obj文件了):

在这里插入图片描述

打开该选项后,编译cpp文件之后,会生成.i文件,即预处理后的文件:

在这里插入图片描述

在这里插入图片描述

现在,来看一下.obj里面是什么内容,直接查看会看到机器码,现在修改一下项目属性:

在这里插入图片描述

这样编译后会生成一个.asm文件,此时用文本编辑器打开它,这基本就是刚刚那个obj文件所含内容的一个可读版本(也就是汇编语言)

在这里插入图片描述

这里会发现会有很多额外的东西,这是因为我们是在debug环境下编译的,而debug是不会做任何优化的,而且会有很多额外的东西,以确保我们的代码尽可能冗长以利于debug。所以现在,回到属性页面:

在这里插入图片描述

此时如果直接编译,会报错,因为O2和RTC不兼容,故继续修改:

在这里插入图片描述

此时再编译可以成功,然后再次查看汇编文件,会发现小了很多(因为之前编译器会插入一些代码来帮助我们debug,现在去掉了):

在这里插入图片描述

linker在联系各个cpp生成的obj文件是,会查找这个函数签名

  • 当我们调用函数时,编译器就会生成一个call指令

总结

编译器会根据我们的源文件(source file)生成包含机器码和我们定义的常量数据的二进制文件(object file)

链接

  • 链接的主要工作就是找到每个符号和函数的位置,并将它们链接到一起。
  • 每一个exe(可执行)文件,都必须有一个入口函数,不一定是main函数,只是必须有一个入口点。
  • 如果链接器找不到一个一模一样的(如,函数名,函数参数,函数返回值),就会出现链接错误。
  • 如果在不同cpp文件中出现了一模一样的(函数),则可以通过编译,但无法通过链接,因为链接器不知道该链接到那个(函数)。

总结

到头来链接器就是在编译之后,将编译过程中生成的所有对象文件链接起来,它还会导入我们可能用到的其他库(如C++标准库)。

一般项目:在头文件中声明函数,cpp文件中定义函数,其他cpp中include此头文件即可。

在这里插入图片描述

声明与定义

  • 声明说明这个函数存在,编译器会无条件相信你
  • 定义则是说这个函数到底是什么,这是这个函数的主体
//Log.cpp

#include<iostream>

void Log(const char* message)
{
	std::cout << message << std::endl;
}
//main.cpp

#include<iostream>

void Log(const char* message);

int main()
{
	Log("Hello World!");
	/*如果只是编译这一个文件,编译器如何知道有一个Log函数在别的文件里呢?
	  回答是,它不知道。但如何正确运行代码呢?
	  这时就需要链接器(linker)了,当我们的文件被编译完毕之后,linker会去找Log的定义
	  然后跟我们main里面调用的函数联系起来,如果它没有找到该函数的定义,我们便会得到一个
	  linker error
	*/
	std::cin.get();
}

补充知识

错误查看相关:

在这里插入图片描述

在这里插入图片描述

  • 当某函数被声明为static时,会意味着对着个函数的链接只发生在该文件内部

错误:

在这里插入图片描述

在链接时找不到相应的函数时会报这种错误

  • 当某函数被声明为static时,会意味着对着个函数的链接只发生在该文件内部
  • 当某函数被声明为inline时,会意味着在链接时只把函数的 身体拿过来取代调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值