目录
关于debug:
多文件编译:
编译器工作原理
预处理:
如何将机器二进制转换成可以看懂的文件
链接器的工作原理
Pointers指针
Reference引用
C++线程
程序如何从源文件变成exe可执行文件?
首先是预处理器#include <...>,获取...文件的全部内容并将其粘贴到main.cpp文件中。
在此阶段,编译器将所有的c++代码转换到实际的机器代码中。
图片中1是项目配置,2是平台 配置
1菜单:调试和发布
2菜单: x86 x64
配置是构建项目时应用的一组规则,平台是编译所针对的平台的设置。
x86是在winow32位下编译,生成32位应用程序。所以win32和x86相同。
项目右键->属性
可以生成exe,还可以生成库文件
编译器运行设置在C/C++,决定文件如何被编译。
调试时优化是被禁用的,但发布没有。
所有的Cpp文件都会被编译,但是Headers文件不被编译,headers包含在预处理阶段。
每一个cpp文件被编译成一个目标文件,然后由linker将编译好的.obj目标文件链接到.exe 文件
Visual Studio可以通过 ctrl+F7 单独编译文件。,或者按Compile按钮。
若没有compile按钮,找到图中的添加或移除按钮->选择-自定义:
然后找到添加命令-生成(build)-编译(compile)
关于debug:
错误列表的工作方式:暂停输出窗口,查找错误并找到有关它的信息,然后将其插入错误列表,但这是非常一般的信息,所以查看错误信息最好到输出窗口。
“未解析的外部符号”意味着链接器找不到定义。链接器是将函数体与其标识符(名称)相关联。
多文件编译:
需要进行声明。声明看起来像定义,但是这里没有函数主体。
声明:某名字、某函数存在。只需要函数名称+参数类型+分号。可以不需要参数名称但指定出来更清楚。
定义:说明函数到底是什么,这是函数主体。
编译器工作原理
编译器在生成目标文件时实际会执行几件事情,首先需要预处理,将预处理语句整理成编译器可以实际理解的格式,这样就可以创建出一个抽象语法树的东西,但最后还是将我们的所有代码转换成常量数据的代码,这些代码就是CPU将执行的实际机器代码。
文件只是一种承载形式,实际编译器只需要被告知如何将文件处理,比如像c++文件或C文件处理
预处理:
预处理语句常用的包括Define if and if def,还有pragma语句。
如何将机器二进制转换成可以看懂的文件
打开属性-> C/C++ -> 汇编程序输出(仅有程序集的列表 /FA)-> 确定 。
然后编译文件,.aim文件即可打开。
链接器的工作原理
链接器的重点是找到每个符号和函数的位置,并将他们链接到一起。每个文件作为翻译单元编译成单独的目标并且这些文件彼此没有关系,链接器就是将这些没有关系的文件链接到一个程序中。
编译不会产生链接,但是构建会产生链接。
错误若是以C开头,则是编译器的错误,若是以LNK开头,则是连接器啊的错误。
每个.exe文件都需要一个函数入口点,其实入口点不一定是main函数,还可以是任何其他函数。
加了stactic,意味着这个函数只是为这个翻译单元声明。
#include的工作原理是当我们包含一个头文件时,我们只是获取该头文件内容并将其放在我们的位置include语句。
Pointers指针
指针是一个整数,一个数字,它存储一个内存地址。
//空指针,无效
void* ptr = NULL;
现在该指针保存的是var变量的16进制的整数内存地址
复制该地址,打开下图内存1
复制地址到地址框,然后按回车键,即可看到该地址值。
指针的类型是被创造出来的意义,实际就是一个整数内存的地址。 只不过可以按指针类型分配合适的内存空间。
无法将10写入一个指针,它不知道 是什么,10是一个短整型,是2个整数;可能是一个int,4位;可能是long long型,是8位整数,所以不清楚到底应该写多少位。所以我们需要的类型是告诉编译器实际上知道这是一个整数,我需要你在其中写入4位。所以将void更改为4位,就对了。
按F10可以继续调试到下一步:
也可以直接搜索变量名buffer
当指针类型变成char*
Reference引用
引用必须引用已经存在的变量。不是新变量占用内存,实际没有存储空间。
看&具体是什么含义还要根据上下文来看,在下图中,&在int类型旁边,&就是引用的含义。此处只有一个变量,ref是对a的引用,使用ref就是在使用a。
成功将引用弹出函数。
引用传递,最后结果也是6,可以对引用做任何不能用指针做的事情
一旦声明一个引用,就不能改变引用的内容。并且声明是就需要初始化
C++线程
#include <iostream>
#include <thread>
static bool s_Finished = false;
void DoWork()
{
using namespace std::literals::chrono_literals;
std::cout << "Start thread id = " << std::this_thread::get_id() << std::endl;
while (!s_Finished)
{
std::cout << "Working...\n";
std::this_thread::sleep_for(1s);
}
}
int main()
{
std::thread worker(DoWork);
std::cin.get();
s_Finished = true;
worker.join();
std::cout << "Finished!" << std::endl;
std::cin.get();
}
多线程时,当不停的去执行某线程,CPU就会变成100%,所以最好加延迟。