IE盒子

搜索
查看: 149|回复: 1

【c++】b站教程记录

[复制链接]

3

主题

7

帖子

13

积分

新手上路

Rank: 1

积分
13
发表于 2023-2-20 21:48:24 | 显示全部楼层 |阅读模式
Welcome to C++

补充基本知识

计算机语言:机器语言➡汇编语言➡高级语言➡自然语言

  • 高级语言:c、c++、python、java等语言
  • 编译器:将高级语言(c++)或者汇编语言作为输入、翻译成计算机可以识别的机器语言(01)
  • 编译器的工作流程:源代码(c++)➡预处理器➡编译器(gcc)➡目标代码(机器语言01)➡链接器➡可执行程序(exe也就是二进制可执行文件)
  • 链接器(Linker):是一个程序、将编译器生成的目标文件+库链接➡可执行文件
  • 例子:记事本也可以写c++只不过需能转化的文档编译器使其转化为程序➡需要集成开发环境IDE(就是一系列的工具 帮助你写代码和debug)(visual studio是现有条件下最好的IDE)
  • 插件(Plus-in):本质也是程序、不能脱离指定的平台独立运行、插件需要调用原系统平台提供的函数库
How to Setup C++ on Windows

c++入门阶段


  • 安置路径时不要含有空格
  • 解决方案solution项目名称project之间的解释:
  • 解决方案solution当成一个包含多个项目project的集合
  • 这些项目project可以是不同类型的(dll、exe、lib等)、每个项目就是文件的集合然后被编译成某种目标二进制文件(lib或者exe)
  • 解决方案solution基本上就是一个工作台
  • 运行程序完会生成一个exe文件(此次实在debug条件下生成 所以在debug)双击Project1.exe就会在黑乎乎cmd界面生成结果


How C++ Works

预处理指令


  • 所有带#的都是预处理指令
  • 比如#include<iostream>:include要做的就是找到iostream文件、将内容复制到当前文件中(include这些文件成为头文件head file)
  • #include<iostream>目的是:需要cout的声明
  • main函数就是计算机执行代码的入口点(entry point)、程序是一行一行被执行的
  • int main() 主函数返回类型return type是一个int型值、如果不指定返回值 系统将会自动返回0
  • 源文件➡编译器(第一件事就是预处理所有的预处理指令、在真正的编译之前)
std::cout<<"hello world"<<std::endl;


  • 可以将<<运算符看作函数、实际上运算符就是函数
  • 与等价std::cout.print("hello world").print(std::endl);
  • cout就是函数、hello world就是cout函数的参数、cout的作用就是将这个参数输出到控制台
可执行程序文件流程


  • 预处理语句preprocessor(#include)会在编译之前被处理
  • 编译:编译器将c++代码转化成实际的机器码
  • (配置管理器中x86和win32是一个意思)
  • 解决方案配置solution configuration(debug、release)(是指如何为这个平台编译的一系列规则)
  • 解决方案平台solution platform(x64、x86是指我们会生成一个用于windows的32位的程序、或者有更复杂的项目有Android 就需要将平台改为Android)(是我们目前编译的目标平台
  • 项目project 属性页面(这个页面就是定义在那些配置平台去如何build的一些规则)
  • (首先要确保屏幕上的配置和平台与属性页面的配置和平台设置一样 否则设置属性页面就无法配置到这个项目中)
  • 编译器的设置位于 c/c++ 中 里面可以设置很多重要选项
  • debug/release的区别可以看两者在c/c++ 优化界面 优化选项为 禁用/最大速度(这也就是debug比release模式下慢很多的原因 而在debug模式下会便于我们调试)
  • 所有的.cpp文件都会被编译、cpp文件是一个个单独编译的、每个cpp文件都将被编译成.obj文件、当每个cpp文件被编译成obj文件后 我们需要将他们联系起来 组成一个exe文件(这就需要linker链接器)
  • .h头文件head file不会被编译 头文件通过预处理指令被include到cpp文件中 那是他们被编译的时刻
  • 写完代码点击编译按钮compile、点击这个按钮 文件就在编译了
  • VS平台中有很多地方显示错误:只看输出窗口的错误显示 双击会显示错误的地方
  • 错误列表不要看 会漏掉很多信息、而他的工作原理是:解析输出窗口 然后寻找错误关键字 放入list中
  • 编译( 1)、生成(中间)、生成解决方案( 1)的区别:编译会生成.obj文件(可以单独编译除main.cpp之外的cpp文件)、生成会生成.exe可执行文件(直接点击项目生成则会生成所有.obj文件和.exe文件)(可以单独先点击编译 出现.obj文件 没点击生成就不会生成可执行文件.exe)
  • (下图是直接点击生成按钮的输出界面 先生成LPR.cpp的.obj文件 再生成main.cpp的.obj文件 最后生成project1.exe文件)
多个cpp文件


  • 写代码 :不同函数分成不同文件、保持清爽条例
  • “cout”:is not a member of 'std' 错误原因:没有将cout的声明include进来、cout是在iostream文件中声明 、添加include<iostream> 这样我们就将cout的声明包含进去了
  • 函数声明declaration:告诉编译器这个函数是存在的
  • 函数定义definition:这个函数是什么 、就是这个函数的主体body
  • 提出问题:怎么知道log函数怎么运行呢
  • 链接器linker就出现了:cpp文件被编译后、linker会去寻找log的定义、跟main函数调用的log函数联系起来、如果找不到定义 将会得到一个linker error








How the C++ compiler works

编译器的目的:只是编译 完全相信计算机所有的函数都存在(万一找不到函数也不会报错 那是链接阶段才会报错)


  • 我们需要某种方法将文本转化为应用 从而在计算机运行
  • (从text到可执行binary)需要有两种操作执行、一个是编译compiling(本次重点讨论)、一个是链接linking
  • c++编译器compiler 将文本代码text变为中继格式.obj(被编译的cpp文件也叫编译单元translation unity)
  • 如果cpp文件互相之间是不包含include(#include关系??)的、那么一个cpp文件就是一个translation unity、如果cpp文件互相之间有包含关系、那么一个translation unity≠一个cpp文件
  • 步骤1:预处理preprocess代码(#include #define #if...等)
  • 步骤2:被预处理后会进入标记解释tokenizing和解析parsing的阶段(将c++语言处理成编译器能处理的语言)
  • 步骤3:步骤2的结果就是创建了抽象语法树abstract syntax tree也就是代码的表达 但是是以抽象语法树的形式、
  • 步骤4:得到抽象语法树后就可以产生cpu会执行的机器码了
  • 说到底编译器的工作就是将代码转化成常数constant data、指令instruction
  • main.cpp没几行代码却占较大的存储空间(因为include了iostream)
  • 比如#include预处理语句的作用:非常简单、include那哪个文件编译器会打开该文件 读取所有内容 粘贴到写include的那个文档
  • 比如以下例子head.h中只有一个符号}
  • 比如#define预处理语句的作用:非常简单、#define a int就是将a替换成int形式
  • 比如#if #endif预处理语句的作用:非常简单、#if 1 #endif相当于执行两者之间的代码、#if 0 #endif相当于注释两者之间的代码
  • 属性 c/c++ 输出文件 汇编程序输出 选择相应的选项可以输出 易读的机器码语言 (汇编代码)
  • debug模式是不会做任何优化的、而且会有很多额外的东西、以确保我们的代码尽可能冗长尽可能易于调试
  • 而在debug优化选项下选择最大优化(优选速度O2)输出的 易读的机器码语言 就会简短很多(这是因为在禁用优化的时候 编译器会加入很多代码 帮助我们进行debug)
  • 编译器工作原理:拿到cpp文件、生成一个包含机器码语言和其他一些我们定义的常数数据的.obj文件







预处理过程的展示 在预处理指令中修改 生成main.i文件



如果#include<iostream> 编译器将iostream文件中所有的东西都复制过来 非常多行


How the C++ Linker Works


  • 链接器的主要工作:找到每个符号和函数的位置 并将他们链接起来
  • 出错类型也能看出来是哪个阶段出现的问题:error C2143(C表示编译阶段compiler)、error LNK2019(LNK表示链接阶段linker)、并且如果同时出现编译错误和链接错误 那么会先报编译错误 改正编译错误之后 再报链接错误(也能表明是先编译后链接的逻辑关系
  • 若是没有定义main函数、在编译阶段或者按下编译按钮的时候不会出错(编译不需要有一个确定的入口点entry point)、生成时将会报错(生成过程是 编译+链接的过程)(生成.exe文件时需要有一个入口点entry point)
常见的链接错误 error link


  • 第一个未解决外部符号unresolved external symbol:当链接器找不到相应函数时(找对应的函数才是linker的功能)
  • 图片处也告诉你找不到哪个函数了(log函数)error LNK:无法解析外部符号"void_cdecl log(char const *)"
  • c包含b b包含a 而a没有找到(LNK报错)、c包含b b不包含a 而a没有声明(LNK正确)
static静态变量函数解释


  • c不包含b b包含a 而a没有声明(LNK报错 难理解解释:技术上来讲我们可能在另一个文件中使用它、因此链接器确实需要链接b、如果有方法告诉链接器我们仅仅在本文件中使用它 因为b函数从未被调用 所以他也不用调用a函数、在b函数前面 添加关键字static 告诉链接器 我们只在本文件中使用它(static静态变量函数)
  • 调用时:函数名称对应很重要、函数类型也很重要(void、int等等)、函数定义的参数也要一致
  • 第二个接到一个或多重定义的符号:出现多重引用函数
  • 解决方法一:在出现多重引用的函数头部 添加static 、这意味对这个log函数链接时 链接只应该发生在该文件内部、也就是说当这个log函数被include在log.cpp中和math.cpp时只会对该文件内部有效(log.cpp和math.cpp会有他们自己版本的log函数(虽然是一样的来源)各自版本的log函数对于其他.obj文件都是不可见的)
  • 解决方法二:在在出现多重引用的函数头部 添加inline 、这意味只调用函数的身体body 也就是函数的主体部分





c不包含b b包含a 而a没有声明(LNK报错)



c不包含b b包含a 而a没有声明 添加static后(LNK正确)



LNK错误:引用同样的多个log、运用static解决

variables in C++


  • 运用c++写程序时 重点是使用数据并且操纵数据、我们想要改变 修改 读写数据都需要将这些数据存储在一个叫做变量的东西中
  • 变量允许存储在内存中的数据 赋一个名字、我们能够玩弄这些数据并存储这些数据
  • 变量被创建时 会被存储在内存的两个地方:stack栈、heap堆
  • c++ 原始数据类型基本构成了在程序中存储任何类型的数据的基础
  • !!!不同的原始变量类型之间的唯一区别就是大小、这个变量占用多少内存上!!!
  • 数据类型的实际大小取决于编译器 不同的编译器占位可能会有所不同
  • 最基本的数据类型:char、int、float、double、bool
  • unsighed关键字的作用:定义一个无符号的关键字 比如:unsigned int(限定这个int整形是没有符号的)
  • char是为了存储字符的 强制转换在数字后面加f 或F
  • sizeof操作符可以知道 变量占用多少字节
  • int4个字节、float4个字节、double8个字节 bool1个字节
  • 内存寻址时 我们只能寻址到bytes字节 而不是bit位(所以尽管bool只占用1个bit 但是我们不能创建1个bit的看数据类型)(但是可以巧妙地将8个bools存在一个字节byte里面)
  • 这些原始类型也可以转换成指针(point在类型旁边加*)和引用(reference在类型旁边加&)
functions in c++


  • 函数:函数被设计用来执行某个特定的任务、是我们编写的代码块
  • class(类)中的代码块被称为methods(方法)
  • 函数封装重复的事件可以简化代码(很重要)代码的目标是应该把你的代码拆分成很多很多的函数
  • 函数的主要目的是防止代码重复
附件:


  • vs整行删除快捷键:shift+del
  • era寄存器学习补充
  • std::cin.get(); 可以让控制台不会瞬间关闭(需要等待我们输入回车才会关闭)
  • 以后写程序可以按照 先列思维导图 将程序的框架打出来 再根据框架细化代码
  • (自己的想法)头文件.h的作用:将main引用其他的     函数声明     集合起来 显得整洁 !!!!头文件:只声明、不定义
  • 函数签名定义:参数及参数的类型、一个返回值及类型、可能会抛出或传回的异常、该方法在面向对象程序中的可用性方面的信息(如public、static或prototype)
回复

使用道具 举报

1

主题

6

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 3 天前 | 显示全部楼层
支持支持再支持
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表