Cherno CPP学习笔记-01-背景知识

发布于:2024-04-09 ⋅ 阅读:(449) ⋅ 点赞:(0)

0、工具网站收集

C++语言版本特性

https://en.cppreference.com

https://www.cplusplus.com

https://www.tutorialspoint.com/cplusplus

https://www.learncpp.com

https://github.com/fffaraz/awesomecpp

https://stackoverflow.com

网页CPP编译器

[C++] gcc 12.1.0 - Wandbox

1.2、开始

P1、欢迎来到C++

C#、Java是在虚拟机上运行的,意味着代码首先编译成一种中间语言,当在目标平台上运行应用程序时,先运行虚拟机,再转换成机器码

C++直接操控硬件,C++编译器为目标平台和目标架构直接生成机器码

P2、环境安装(windows)

VS2017的安装教程

File->new project->Visual C++ ->General->Empty Project

然后起好名字、确定好路径就ok了

进入项目,在Solution Explorer中自己的Solution下的Source File->add->new Item

P5、C++是如何工作的

#符号后面都是预处理语句,编译器会首先处理(编译发生之前)

main函数比较特殊,不一定非要返回值(没写的话默认返回0)

#include<iostream>

int main() {
	std::cout << "hello World!" << std::endl;
	std::cin.get();

}

运行顺序:

  • 编译器先处理“预处理语句”,即编译器先将iostream文件内容全部包含进来,可以理解为拷贝粘贴到自己的文件中

  • 第二步,文件被编译,编译器将所有的C++代码转换为实际的机器代码。以VS配置为例:

    • 解决方案平台(默认Debug 和 x86或win32)
    • 配置只是构建项目的时候的一系列规则(右键解决方案->属性)
    • 解决方案是指你编译的代码的目标平台
    • x86的意思就目标平台为windows 32位,会生成32位的windows应用程序
    • 目标平台也可以是Android,但要确保配置和平台的正确
    • Debug和release的区别:默认Debug会更慢,release更追求速度。Debug关掉了很多优化以方便我们更好调试代码。
    • 配置类型是生成文件的格式.exe .dll
    • 包括C/C++下的配置,这些规则控制我们的文件如何被编译
    • 在程序员的视角,编译只编译 .cpp文件,因为头文件被复制粘贴进 .cpp文件中了
    • 每一个cpp文件都被编译成了一个object file(目标文件),vs生成的文件后缀是.obj
  • 然后,链接(link)将生成的.obj文件合并成一个执行文件: How the C++ Linker Works

    • 单独编译一个文件,不会发生链接

请添加图片描述

PS: error list仅供参考,一般信息不全,建议看output 窗口。

link的一个例子 (使用声明):

//main.cpp
#include<iostream>

void Log(const char* message);

int main() {
	Log("hello World");
	std::cin.get();

}
//log.cpp
#include<iostream>

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

P6、C++编译器是如何工作的

编译原理既视感

请添加图片描述

相比其他语言,在C++里,文件变得没有意义

  • Java里主类命要与 .java 名字一致,包名的命名层级关系,文件可以被看做是组成单元
  • 但在C++里,文件更像是一种协议或者是约定,.cpp被视为c++文件, .c 被视为c文件, .h被视为头文件,不同的文件对应的“约定”不同。
  • 编译器只是将一个cpp文件变成一个翻译单元,一个翻译单元会生成一个.obj文件,实际上cpp文件可以包含其他的cpp文件,最后也是一个翻译单元

一个成功编译的例子:(#include的复制粘贴)

int Mutiply(int a, int b)
{
    int result = a * b;
    return result;
#include "EndBrace.h"
//EndBrace.h
}
  • 在项目属性->C/C+±>Output Files->Assembler Output设置为/FA,编译之后就会生成一个.asm文件,内容为汇编指令。

  • 在项目属性->C/C+±>Optimization设置为Maximum Speed并且把Code Generation->Basic Runtime Checks设置成Default,编译之后再看.asm文件,发现文件相比之前的设置小了许多,这是因为编译器对代码做了优化。

1.5、继续(巫师3真好玩)

P7、C++链接器是如何工作的

链接的主要工作:找到每个符号和每个函数在哪里,并把他们连接起来。即把所有的.obj文件链接在一起。

链接过程常见错误:(错误代码LNK)

  • 未解决的外部符号unresolved external symbol : 连接器找不到他们需要的东西。

如果从来没有调用过某个函数(代码级),那么链接器不需要去链接这个函数。反之可能有例外:

static修饰的函数意味着这个函数只被声明在当前翻译单元中

//Main.cpp
//代码上Multiply函数中调用了Log函数,如果去链接Log函数将会出错
//但由于static的修饰,链接器判断Multiply函数将不可能被调用(本翻译单元内未调用+其他翻译单元不使用Mutiply)
//故编译和链接过程都不会出错。
//去掉static或者main中的注释//都会导致出错
#include<iostream>

void Log(const char* message);

static int Multiply(int a, int b){
	Log("Multiply");
	return a * b;
}

int main() {
	//std::cout << Multiply(5, 8) << std::endl;
	std::cin.get();
}
//Log.cpp
#include<iostream>

void LogR(const char* message) {
	std::cout << message << std::endl;
}

  • 静态链接
  • 动态链接

P8、C++变量

核心思想,不同变量之间的区别是分配的空间大小。

P9、C++函数

没什么东西

P10、C++头文件

#pragma once在头文件中的作用:

  • 告诉编译器这个头文件只被编译一次
  • 尤其防止 .h 文件中出现结构体重复编译将会报错

另一种做法做法:(头文件保护符)

#ifndef _LOG_H
#define _LOG_H

void Log(const char* message);
void InitLog();
struct Player{};

#endif

#include 尖括号<>和引号""的区别:

  • 如果要包含的文件在其中一个文件夹里,用尖括号告诉编译器搜索包含路径的文件夹
  • 引号通常用于包含相对于当前文件的文件,但引号其实可以做一切。

P11、如何在Visual Studio中调试

在debug模式下,内存视图中值为 0xCC 的内存为未初始化的栈空间


网站公告

今日签到

点亮在社区的每一天
去签到