了解C++工作机制

基于hello.cpp对C++的运行进行一个初步认识,并介绍国外C++大佬Cherno常用的项目结构和调试Tips

C++是如何工作的

  • C++工作流程
  • 1.实用工程(project)结构
    • (1)Microsoft Visual Studio2022新建项目后,自动生成的原始文件和文件夹:
    • (2)写一个简单的main.cpp,编译运行后,自动创建文件加和生成中间文件(obj)和可执行文件(exe)
    • (3)从默认工程/项目(project)结构到实用工程/项目结构
  • 2.调试(debug)
    • 3.1整体代码
    • 3.2预处理
    • 3.3.编译
    • 3.4链接
  • 4.C++编译器
    • 4.1定义与作用
    • 4.2示例
    • 4.3编译器的优化代码例子 ——“常数折叠”
  • 5.C++链接器
  • 6.头文件
    • 6.1定义与作用
    • 6.2示例
    • 4.3在实现函数的 functions.cpp 文件中包含 #include "functions.h" 的目的

C++工作流程

1.实用工程(project)结构

(1)Microsoft Visual Studio2022新建项目后,自动生成的原始文件和文件夹:

在这里插入图片描述

(2)写一个简单的main.cpp,编译运行后,自动创建文件加和生成中间文件(obj)和可执行文件(exe)

在这里插入图片描述

在这里插入图片描述

(3)从默认工程/项目(project)结构到实用工程/项目结构

  1. 实用如下修改输出目录和中间目录
$(SolutionDir)bin\$(Platform)\$(Configuration)\
$(SolutionDir)bin\intermediates\$(Platform)\$(Configuration)\
-$(SolutionDir)代表当前解决方案,不同的的解决方案会进行不同的具体的实例化,$(Platform)以此类推

在这里插入图片描述
在这里插入图片描述
2. 切换为“显示所有文件”的视图,并且新建一个src文件夹,用于收录.cpp文件
在这里插入图片描述
在这里插入图片描述

3.写一个简单的cpp文件,并且查看编译运行后的目录结构
在这里插入图片描述
在这里插入图片描述

这样的目录结构是不是更清晰喜人呢?

2.调试(debug)

在这里插入图片描述
Ctrl+F5进入调试模式,F11可单步执行,调试–>窗口–>内存–>内存1,可以查看当前程序使用的内存的内存的状态
在这里插入图片描述

断点之上的代码已经运行,断点及断点之下的代码将要运行,这里我们键入参数a的地址,并且回车
在这里插入图片描述

在这里插入图片描述

3.1整体代码

#include<iostream>int main()
{std::cout << "hello, cpp!" << std::endl;std::cin.get();return 0;
}
}

3.2预处理

预处理(Preprocessing)是 C++ 编译过程中的第一个阶段,它在实际的编译之前对源代码进行一系列的文本替换和处理操作。

#include <iostream>

在编译之前,C++ 编译器会进行预处理,经预处理后,iostream文件中的内容就被copy到我们的源文件中了。
项目中每一个cpp文件都会被编译,但头文件不会被编译,因为其已经被预处理过了。

3.3.编译

编译是将高级程序设计语言(如C++)编写的源代码转换成计算机可以执行的机器代码的过程。

cpp的代码正常情况下是从上到下一行一行编译的(头文件不会被执行编译,其在预处理时被包含进来,和后面的代码一起编译)。

#include<iostream> int main()
{std::cout << "hello, cpp!" << std::endl;std::cin.get();return 0}

完成编译后,生成了obj文件。在 Windows 平台上,“.obj” 文件通常是使用 Microsoft Visual Studio 编译器生成的。

在这里插入图片描述

obj文件包含了编译器对源代码的翻译结果。 这个文件中包含了与源代码中的每个函数和变量相关的机器代码,并且还可能包含一些调试信息、符号表、重定位信息等。目标文件的生成是编译的一部分,它还需要经过链接过程,与其他目标文件和库文件一起生成最终的可执行文件(exe)。

3.4链接

链接(Linking)是 C++编译过程中的一个重要阶段,它将编译器生成的目标文件和其他可能用到的目标文件或库文件合并成最终的可执行文件。

在这里插入图片描述

每一个cpp源文件都对应一个obj,链接器将其连接后,生成可执行文件。

增加一个cpp源文件,如下:

#include<iostream>void log(const char* message)
{std::cout << message << std::endl;
}

对其编译后,在debug文件夹下会看到其生成的obj文件:

在这里插入图片描述

4.C++编译器

4.1定义与作用

C++编译器是一种将C++源代码翻译成目标代码(通常是机器代码)的工具。其工作包括词法分析、语法分析、语义分析、优化和代码生成等阶段。

  • 词法分析(Lexical Analysis):编译器首先会将源代码分解成基本单元,这些单元被称为词法单元(tokens),比如关键字、标识符、运算符等。

  • 语法分析(Syntax Analysis):在这个阶段,编译器将词法单元组织成语法树,以检查代码的结构是否符合语法规则。

  • 语义分析(Semantic Analysis):编译器会检查代码的语义是否合法,比如变量是否被正确声明和使用,函数是否正确调用等。

  • 优化(Optimization):在生成目标代码之前,编译器可能会进行一系列的优化操作,以提高程序的性能或减小生成的目标代码的体积。

  • 代码生成(Code Generation):最终阶段是生成目标代码,这是计算机可以直接执行的机器代码。这些代码通常是针对特定硬件架构的。

4.2示例

#include <iostream>int main() {int x = 5; // 变量声明和赋值int y = 10;int result = x + y; // 加法操作std::cout << "The result is: " << result << std::endl;return 0;
}

在这个示例中,编译器将首先进行词法分析,将代码分解成词法单元。然后进行语法分析,构建语法树。接着进行语义分析,确保变量被正确声明和使用。最后,编译器会生成目标代码,执行加法操作并输出结果。这是一个简化的过程,实际编译器会进行更多的优化和处理。

4.3编译器的优化代码例子 ——“常数折叠”

常数折叠(Constant Folding)是指编译器在编译阶段对常量表达式进行计算,并将其结果直接替换回表达式的值。这个过程发生在编译器静态分析阶段,有助于优化代码,减少运行时的计算量。

举个例子:

int result = 5 + 3 * 2;

在常数折叠过程中,编译器会对表达式进行计算。在这个例子中,3 * 2是一个常量表达式,编译器可以在编译阶段计算出其结果为6。因此,整个表达式可以被折叠为:

int result = 5 + 6;

这个过程可以减少程序运行时的计算量,提高代码的执行效率。

5.C++链接器

链接器(Linker)是编译器工具链中的一个部分,它负责将多个目标文件(Object Files)或者库文件(Library Files)中的代码和数据结合起来,生成最终的可执行文件或者库文件。在程序编译过程中,源代码会被编译成目标文件,这些目标文件可能包含了程序的不同部分,比如函数、变量等。

链接器的主要任务包括:

  • 符号解析(Symbol Resolution):处理各个目标文件中使用的符号(如函数、变量名),将其与实际的内存地址或者其他目标文件中的符号联系起来。

  • 符号合并(Symbol Combining):将各个目标文件中定义的符号整合到最终的输出文件中,解决多个目标文件中可能存在的重复定义。

  • 地址重定位(Address Binding):将各个目标文件中的符号地址绑定到最终的可执行文件或库文件中,以便在程序加载到内存并执行时,能够正确地定位和访问各个符号。

  • 生成可执行文件或库文件(Executable or Library Generation):最终将链接后的目标文件生成可执行文件(例如.exe文件)或者库文件(例如.dll或.lib文件),供操作系统或其他程序使用。

链接器的工作分为静态链接和动态链接两种方式。静态链接是将所有的目标文件和库文件在编译时链接成一个完整的可执行文件,而动态链接是在程序运行时才进行链接,可以实现共享库(Shared Library)的功能。

总的来说,链接器在编译过程的最后阶段,将各个模块或库文件整合在一起,生成可执行的程序或者库文件,使得程序能够正确地运行。

6.头文件

6.1定义与作用

头文件(Header File)是一种文本文件,通常以.h为扩展名,包含了函数、类、变量等的声明和定义。头文件的主要作用是提供接口和声明,让程序能够访问和使用某些功能而无需了解其具体实现细节。

头文件的作用包括:

  • 声明和接口提供: 头文件通常包含函数、类、变量的声明,允许在不暴露实现细节的情况下使用这些元素。其他文件可以包含头文件,从而访问其中声明的内容,而不必了解其实现细节。

  • 模块化和组织性: 头文件有助于组织代码,将相关的功能组织到单独的模块中,并通过包含不同的头文件来实现模块化。这样可以提高代码的可维护性和可读性。

  • 重用和共享代码: 头文件中的声明和接口可以被多个文件共享和重用,使得相同的函数、类或变量能够在多个文件中使用,减少重复编写代码的工作量。

头文件在以下场景中能够发挥作用:

  • 多文件项目: 当程序由多个源文件组成时,头文件能够提供接口和声明,使得各个文件能够互相访问和使用彼此的功能,提高了代码的组织性和可维护性。

  • 库开发: 在开发库或框架时,头文件对外提供了公共接口和声明,允许其他开发者使用库的功能而无需了解其内部实现。

  • 项目协作: 在团队协作开发项目时,头文件定义了函数、类等的接口,让团队成员了解如何使用这些接口而无需深入了解实现细节。

6.2示例

创建头文件(例如:functions.h):头文件包含函数的声明和可能的结构、常量或其他相关内容。

// functions.h
#pragma once// 函数声明
int add(int a, int b);
float divide(float a, float b);

在源文件中包含头文件:在需要使用这些函数的源文件中,包含头文件。

// main.cpp#include <iostream>
#include "functions.h" // 包含头文件int main() {int result = add(5, 3); // 调用头文件中声明的函数std::cout << "Result: " << result << std::endl;return 0;
}

实现函数:在源文件中实现头文件中声明的函数。

// functions.cpp#include "functions.h" // 包含对应的头文件int add(int a, int b) {return a + b;
}float divide(float a, float b) {if (b != 0) {return a / b;} else {return 0; // 可以根据实际需求进行异常处理或错误提示}
}

好处:

  • 模块化和组织性: 使用头文件可以将函数的声明和结构、常量等信息组织在一起,使得代码更模块化和易于维护。

  • 可读性: 头文件提供了函数接口的清晰定义,使得阅读和理解代码更为容易。

  • 代码重用: 通过头文件的方式,可以在多个源文件中重复使用相同的函数声明,提高了代码的重用性。

  • 错误检查: 预编译器指令(#ifndef、#define、#endif)用于防止头文件被多次包含,避免了重复定义和编译错误。

  • 维护方便: 当需要修改函数接口时,只需在头文件中修改函数的声明,而不必修改所有使用该函数的源文件。

4.3在实现函数的 functions.cpp 文件中包含 #include “functions.h” 的目的

在实现函数的 functions.cpp 文件中包含 #include “functions.h” 是为了确保函数的实现与其声明一致。这样做有以下作用:

  • 检查一致性: #include “functions.h” 会将头文件中的函数声明包含到 .cpp 文件中,这样编译器就能检查函数的实现是否与其声明一致。如果实现与声明不一致,编译器会报错,提醒修正错误。

  • 可读性和维护性: 包含头文件可以让读者清晰地看到函数的接口和声明。这样使得代码更易读、易懂,并且方便维护。

  • 代码一致性: 保持函数声明和定义的一致性是良好编程实践的一部分,有助于代码的可靠性和一致性。

在某些情况下,如果函数的实现非常简单,不需要使用头文件中的其他信息(例如结构、常量等),有时可以省略包含头文件。但是,为了代码的可读性和一致性,我们最好在函数的实现文件中包含对应的头文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/233399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创建型设计模式 | 原型模式

一、原型模式 1、原理 原型模式&#xff0c;用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象再创建另外一个可定制的对象&#xff0c;而且不需要知道任何创建的细节。原型像是一个模板&#xff0c;可以基于它复制好多…

轻量封装WebGPU渲染系统示例<49>- 多种灯光多材质(源码)

实现方式: 1. 全局的灯光和阴影。 2. 球体和矩形平面使用了相同的材质对象。 3. 通过材质自动关联和组装对应的渲染材质功能节点。 4. 共享uniform或storage的buffer对象。 5. 共享shader module对象。 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/b…

排序嘉年华———选择排序和快排原始版

文章目录 一.选择排序二.霍尔版快速排序1.单趟思想2.递归多趟3.寻找中间值作为key 一.选择排序 在进行大佬“快排”之前先来一道开胃小菜————选择排序 选择排序是一种简单直观的排序算法&#xff0c;它的基本思想是每一次从待排序的数据元素中选出最小&#xff08;或最大&…

12 v-if指令

概述 v-if指令主要用来实现条件渲染&#xff0c;在实际项目中使用得也非常多。 v-if通常会配合v-else-if、v-else指令一起使用&#xff0c;可以达到多个条件执行一个&#xff0c;两个条件执行一个&#xff0c;满足一个条件执行等多种场景。 下面&#xff0c;我们分别演示这三…

AWS Linux安装桌面并远程访问

文章目录 小结问题及解决参考 小结 在AWS Linux安装了桌面并进行远程访问。 问题及解决 需要使用过程桌面访问AWS Linux&#xff0c;这里在AWS服务器安装并使用Amazon Linux 2 MATE desktop。 检查OS版本&#xff1a; [ec2-userip-10-0-3-241 ~]$ grep PRETTY_NAME /etc/o…

基于“Galera+MariaDB”搭建多主数据库集群的实例

1、什么是多主数据库集群 多主数据库集群是一种数据库集群架构&#xff0c;每个节点都可以接收写入操作和读取操作&#xff0c;并且通过心跳机制同步数据&#xff0c;保证数据一致性和高可用性。因多主数据库集群每个节点都可以承担读写操作&#xff0c;因此它可以充分利用各个…

1.【分布式】分布式事务详解

分布式事务 1.分布式事务是什么&#xff1f;数据库事务 2.分布式事务产生的原因&#xff1f;存储层拆分服务层拆分 3.分布式事务解决方案4.分布式事务有哪些开源组件SeateTCC 分布式服务组件基于消息补偿的最终一致性 5.两阶段提交&#xff0c;三阶段协议详解二阶段提交协议三阶…

Node.js使用Express框架写服务端接口时,如何将接口拆分到不同文件中

项目目录结构说明&#xff1a; node.js连接mysql数据库步骤可参考&#xff1a;Node.js 连接 MySQL | 菜鸟教程 1、拆分之前的写法&#xff0c;未区分模块&#xff0c;所有接口api都写在了入口文件app.js中&#xff1b; 需求&#xff1a;想要将接口api拆分成根据不同的业务模块…

Gin之GORM多表关联查询(多对多;自定义预加载SQL)

数据库三个,如下: 注意:配置中间表的时候,表设计层面最好和配置的其他两张表契合,例如其他两张表为fate内的master和slave;要整合其对应关系的话,设计中间表的结构为master_id和slave_id最好(不然会涉及重写外键的操作) 重写外键(介绍) 对于 many2many 关系,连接表…

K8s攻击案例:RBAC配置不当导致集群接管

01、概述 Service Account本质是服务账号&#xff0c;是Pod连接K8s集群的凭证。在默认情况下&#xff0c;系统会为创建的Pod提供一个默认的Service Account&#xff0c;用户也可以自定义Service Account&#xff0c;与Service Account关联的凭证会自动挂载到Pod的文件系统中。 …

spring MVC概述和土门案例(无配置文件开发)

SpringMVC 1&#xff0c;SpringMVC概述2&#xff0c;SpringMVC入门案例2.1 需求分析2.2 案例制作步骤1:创建Maven项目步骤2:补全目录结构步骤3:导入jar包步骤4:创建配置类步骤5:创建Controller类步骤6:使用配置类替换web.xml步骤7:配置Tomcat环境步骤8:启动运行项目步骤9:浏览器…

phpmyadmin4.8.1远程文件包含漏洞 [GWCTF 2019]我有一个数据库1

打开题目 我们用dirsearch扫描一下后台看看 扫描结果如下 我们访问一下robots.txt看看&#xff0c;提示有phpinfo.php 那我们访问一下phpinfo.php 发现没有任何信息后我们转去看看phpmyadmin看看 成功访问到页面 在这里我们看到phpmyadmin的版本号是4.8.1 我们百度搜索一下看…

GitHub 如何修改 Fork from

如果你的仓库上面是 Fork from 的话&#xff0c;我们有什么办法能够取消掉这个 Fork from&#xff1f; 解决办法 GitHub 上面没有让你取消掉 Fork 的办法。 如果进入设置&#xff0c;在可见设置中也没有办法修改仓库的可见设置选项。 唯一的解决办法就是对你需要修改的仓库先…

使用Axure的中继器的交互动作解决增删改查h

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《产品经理如何画泳道图&流程图》 ⛺️ 越努力 &#xff0c;越幸运 目录 一、中继器的交互 1、什么是中继器的交互 2、Axure中继器的交互 3、如何使用中继器&#xff1f; 二…

在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装教程

在 VMware 虚拟机上安装黑苹果(Hackintosh)&#xff1a;免费 macOS ISO 镜像下载及安装教程 VMware 虚拟机解锁 macOS 安装选项使用 macOS iso 系统镜像安装使用 OpenCore 做引导程序安装 在 VMware 虚拟机上安装黑苹果(Hackintosh)&#xff1a;免费 macOS ISO 镜像下载及安装…

Python Pandas Excel/csv文件的保存与读取(第14讲)

Python Pandas Excel/csv文件的读取于保存(第14讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

VSCode报错插件Error lens

1.点击左侧扩展图标→搜索“error lens”→点击“安装” 2.安装成功页面如下&#xff1a; 3.代码测试一下&#xff1a;书写代码的过程中会出现红色提醒或红色报错 4.另外推荐小伙伴们安装中文插件&#xff0c;学习过程中会比较实用方便&#xff0c;需要安装中文插件的小伙伴请点…

【SQL】根据年月,查询月份中每一天的数据量

传入YYYY-MM-01&#xff0c;查询这个月中每一天的数据量&#xff0c;没有数据的天数用0表示 WITH RECURSIVE DateRange AS (SELECT :startDate AS DateUNION ALLSELECT DATE_ADD(Date, INTERVAL 1 DAY) FROM DateRangeWHERE Date < LAST_DAY(:startDate) ) SELECTdr.Date,CO…

限流原理与实践:固定窗口、滑动窗口、漏桶与令牌桶解析

方案一、固定窗口限流算法 这里我们通过一个 demo 来介绍固定窗口限流算法。 创建一个 FixWindowRateLimiterService 类。 Service public class FixWindowRateLimiterService {Resourceprivate StringRedisTemplate stringRedisTemplate;private static final DefaultRedisSc…

[Toolschain cpp ros cmakelist python vscode] 记录写每次项目重复的设置和配置 不断更新

写在前面 用以前的设置&#xff0c;快速配置项目&#xff0c;以防长久不用忘记&#xff0c;部分资料在资源文件里还没有整理 outline cmakelist 复用vscode 找到头文件vscode debug现有代码直接关联远端gitros杂记repo 杂记glog杂记 cmakelist 复用 包含了根据系统路径找库…