diff --git a/yuwenhao/IAR/IAR.pdf b/yuwenhao/IAR/IAR.pdf new file mode 100644 index 0000000..53685fb Binary files /dev/null and b/yuwenhao/IAR/IAR.pdf differ diff --git a/yuwenhao/VisualStudio/VisualStudio.md b/yuwenhao/VisualStudio/VisualStudio.md index e69de29..c054f71 100644 --- a/yuwenhao/VisualStudio/VisualStudio.md +++ b/yuwenhao/VisualStudio/VisualStudio.md @@ -0,0 +1,2059 @@ +# Visual Studio 2019 学习文档 + +## 1. 学习目标 + +本文档用于记录 Visual Studio 2019 的基础操作学习内容,主要围绕工程创建、工程配置和工程调试三个方面展开。 + +完成本文档学习后,应能够完成以下操作: + +1. 熟练创建、打开、加载、卸载 Visual Studio 工程; +2. 理解解决方案、项目、文件之间的关系; +3. 熟练配置解决方案配置、平台配置、项目类型、输出路径、头文件路径、库文件路径等常用选项; +4. 掌握宏定义、运行库、调用库、安全检查等基础配置; +5. 熟练使用断点、监视窗口、内存窗口、线程窗口、调用堆栈窗口; +6. 掌握全速运行、重新运行、逐过程、逐语句等调试方式。 + +## 2. 文档目录结构 + +VisualStudio 学习文档按照基础学习要求进行存放,推荐目录结构如下: + +```text +VisualStudio +|---pictures +| |---VS2019_001_启动界面.png +| |---VS2019_002_创建项目.png +| |---VS2019_003_解决方案资源管理器.png +| |---VS2019_004_项目属性页.png +| |---VS2019_005_断点调试.png +| +---VS2019_006_调试窗口.png ++---VisualStudio.md +``` + +图片统一放在 `pictures` 文件夹下,Markdown 文档中通过相对路径进行引用。 + +## 3. Visual Studio 基本概念 + +### 3.1 Visual Studio 是什么 + +Visual Studio 是 Microsoft 提供的集成开发环境,常用于 C、C++、C# 等程序开发。对于 C/C++ 工程来说,Visual Studio 可以完成代码编辑、工程管理、编译、链接、运行和调试等工作。 + +在学习 VS2019 时,不能只会写代码,还要理解工程结构、编译配置、链接配置和调试方法。 + +### 3.2 解决方案、项目、文件的关系 + +VS2019 中常见的层级关系如下: + +```text +解决方案 Solution +|---项目 Project 1 +| |---头文件 Header Files +| |---源文件 Source Files +| +---资源文件 Resource Files +| ++---项目 Project 2 + |---头文件 Header Files + |---源文件 Source Files + +---资源文件 Resource Files +``` + +各部分含义如下: + +| 名称 | 含义 | +| ---- | -------------------------------------------- | +| 解决方案 | 用于统一管理一个或多个项目,文件后缀通常为 `.sln` | +| 项目 | 一个可以独立配置、编译、生成的工程,C/C++ 项目文件后缀通常为 `.vcxproj` | +| 头文件 | 一般为 `.h` 文件,用于函数声明、宏定义、结构体声明等 | +| 源文件 | 一般为 `.c` 或 `.cpp` 文件,用于函数实现 | +| 资源文件 | 图标、界面、资源脚本等文件,普通控制台程序中不一定使用 | + +简单理解:解决方案是一个大文件夹,项目是里面的具体工程,文件是工程中真正参与编译和管理的代码文件。 + +![VS2019解决方案资源管理器](pictures/VS2019_003_解决方案资源管理器.png) + +## 4. 工程创建 + +工程创建部分主要学习 VS2019 中“解决方案、项目、文件”三者的基本管理方法。实际开发时,不能只会新建一个工程,还要会打开已有工程、加载或卸载项目、设置启动项目、向解决方案中添加项目,以及管理项目中的源文件和头文件。 + +本章对应要求如下: + +```text +工程创建 +|---工程相关 +| |---创建/打开项目 +| |---加载/卸载项目 +| +---设置启动项 +|---解决方案相关 +| +---添加项目 ++---文件相关 + |---创建/打开文件 + +---包括/排除文件 +``` + +### 4.1 创建项目 + +#### 4.1.1 创建项目的含义 + +创建项目就是在 VS2019 中新建一个可以被编译、链接和调试的工程。项目中可以包含源文件、头文件、资源文件以及工程配置。对于 C/C++ 学习来说,项目通常会生成 `.exe`、`.lib` 或 `.dll` 文件。 + +常见项目类型如下: + +| 项目类型 | 生成结果 | 适用场景 | +| ----- | -------- | ------------------------------- | +| 控制台应用 | `.exe` | 学习 C/C++ 基础语法、普通程序调试 | +| 空项目 | 根据后续配置决定 | 适合手动添加 `.c/.cpp/.h` 文件,便于理解工程结构 | +| 静态库 | `.lib` | 将一部分代码封装成库,供其他项目调用 | +| 动态链接库 | `.dll` | 运行时被其他程序加载调用 | + +学习 VS2019 基础操作时,建议优先创建 `空项目`,因为空项目不会自动生成太多文件,工程结构更清楚。 + +#### 4.1.2 创建空项目操作步骤 + +操作步骤: + +1. 打开 `Visual Studio 2019`; + +2. 在启动界面点击: + + ```text + 创建新项目 + ``` + +3. 在搜索框中输入: + + ```text + 空项目 + ``` + +4. 选择 C++ 分类下的: + + ```text + 空项目 + ``` + +5. 点击: + + ```text + 下一步 + ``` + +6. 设置项目信息: + + | 设置项 | 示例 | 说明 | + | ------ | --------------------------- | ------------- | + | 项目名称 | `VS_Demo` | 当前项目的名称 | + | 位置 | `D:\TrainCamp\VisualStudio` | 项目保存路径 | + | 解决方案名称 | `VS_Demo` | 解决方案名称,可与项目同名 | + +7. 点击: + + ```text + 创建 + ``` + +8. 创建完成后,在右侧 `解决方案资源管理器` 中可以看到解决方案和项目。 + +![创建空项目](pictures\VS2019_002_创建项目.png) + +#### 4.1.3 创建完成后的工程结构 + +创建空项目后,解决方案资源管理器中通常可以看到如下结构: + +```text +解决方案“VS_Demo” ++---VS_Demo + |---引用 + |---外部依赖项 + |---头文件 + |---源文件 + +---资源文件 +``` + +各部分说明如下: + +| 名称 | 说明 | +| ---- | ------------------------------------- | +| 解决方案 | 用来管理一个或多个项目,后缀一般为 `.sln` | +| 项目 | 真正参与编译和生成的工程,C/C++ 项目后缀一般为 `.vcxproj` | +| 头文件 | 用来存放 `.h` 文件 | +| 源文件 | 用来存放 `.c` 或 `.cpp` 文件 | +| 资源文件 | 用来存放图标、资源脚本等文件,普通控制台程序可以不使用 | + +注意:刚创建的空项目没有 `main.cpp`,此时直接运行会报错,需要先手动添加源文件。 + +### 4.2 打开项目 + +#### 4.2.1 打开项目的含义 + +打开项目是指打开一个已经存在的 VS2019 工程。实际工作中,别人发来的工程或者从代码仓库拉取下来的工程,一般不需要重新创建,而是直接打开已有解决方案。 + +VS2019 中常见文件后缀如下: + +| 文件后缀 | 含义 | 是否推荐直接打开 | +| ------------ | ---------------- | ------------------ | +| `.sln` | 解决方案文件,管理一个或多个项目 | 推荐 | +| `.vcxproj` | C/C++ 项目文件 | 可以打开,但不如 `.sln` 完整 | +| `.cpp/.c/.h` | 普通代码文件 | 只会打开文件,不等于打开工程 | + +一般情况下,打开工程时优先选择 `.sln` 文件。 + +#### 4.2.2 打开已有解决方案 + +操作步骤: + +1. 打开 `Visual Studio 2019`; + +2. 点击: + + ```text + 打开项目或解决方案 + ``` + +3. 找到工程目录; + +4. 选择后缀为 `.sln` 的文件,例如: + + ```text + VS_Demo.sln + ``` + +5. 点击: + + ```text + 打开 + ``` + +6. 等待项目加载完成; + +7. 在 `解决方案资源管理器` 中确认项目是否正常显示。 + +![打开解决方案](F:\信捷电气\训练营\第一周\学习文档\yuwenhao\VisualStudio\pictures\VS2019_002.png) + +#### 4.2.3 只打开文件和打开项目的区别 + +很多初学者会直接双击 `.cpp` 文件,这样虽然能看到代码,但并不代表工程已经被打开。 + +| 操作方式 | 结果 | 是否能完整编译调试 | +| ------------- | ------------- | --------- | +| 打开 `.sln` | 打开完整解决方案和项目配置 | 可以 | +| 打开 `.vcxproj` | 打开单个项目 | 一般可以 | +| 打开 `.cpp` | 只打开一个代码文件 | 不一定可以 | + +所以在验收或实际开发中,应优先通过 `.sln` 打开完整工程。 + +### 4.3 加载项目和卸载项目 + +#### 4.3.1 加载/卸载项目的含义 + +一个解决方案中可以包含多个项目。加载项目表示该项目当前被 VS2019 正常打开,可以查看、配置和生成。卸载项目表示该项目暂时不参与当前解决方案的加载和生成,但项目文件并没有被删除。 + +简单理解: + +```text +卸载项目 = 临时让项目休息,不是删除项目 +重新加载项目 = 让项目重新回到解决方案中 +``` + +#### 4.3.2 卸载项目操作步骤 + +操作步骤: + +1. 在左侧打开: + + ```text + 解决方案资源管理器 + ``` + +2. 找到需要卸载的项目; + +3. 右键点击该项目名称; + +4. 选择: + + ```text + 卸载项目 + ``` + +5. 卸载后,项目名称会变成灰色,表示当前项目已经卸载。 + +![卸载项目](pictures/VS2019_003_卸载项目.png) + +#### 4.3.3 重新加载项目操作步骤 + +操作步骤: + +1. 在 `解决方案资源管理器` 中找到已经卸载的项目; + +2. 右键点击该项目; + +3. 选择: + + ```text + 重新加载项目 + ``` + + ![](pictures\重新加载项目.png) + +4. 项目恢复正常显示; + +5. 此时可以继续查看、修改、编译该项目。 + +#### 4.3.4 加载/卸载项目的常见用途 + +| 使用场景 | 说明 | +| ------------------ | ---------------- | +| 解决方案中项目很多 | 暂时卸载无关项目,减少干扰 | +| 某个项目暂时编译不过 | 可以先卸载该项目,只调试其他项目 | +| 查看 `.vcxproj` 文件内容 | 卸载项目后可以右键编辑项目文件 | +| 多项目联合开发 | 需要哪个项目就加载哪个项目 | + +注意:卸载项目不会删除磁盘上的代码文件,也不会删除 `.vcxproj` 项目文件。 + +### 4.4 设置启动项 + +#### 4.4.1 启动项的含义 + +启动项就是按 `F5` 或点击 `本地 Windows 调试器` 时,VS2019 默认运行的项目。 + +当一个解决方案里只有一个项目时,一般不需要特别设置;当一个解决方案里有多个项目时,必须确认哪个项目是启动项。 + +例如一个解决方案中有两个项目: + +```text +解决方案 DemoSolution +|---App_Main 生成 exe,主程序 ++---Math_Lib 生成 lib,静态库 +``` + +此时应该把 `App_Main` 设置为启动项,因为 `.lib` 静态库不能直接运行。 + +#### 4.4.2 设置启动项操作步骤 + +操作步骤: + +1. 在 `解决方案资源管理器` 中找到需要运行的项目; + +2. 右键点击该项目; + +3. 选择: + + ```text + 设为启动项目 + ``` + +4. 设置成功后,该项目名称一般会加粗显示; + +5. 按 `F5` 或点击: + + ```text + 本地 Windows 调试器 + ``` + +6. VS2019 会编译并运行当前启动项目。 + +![设置启动项](pictures/设置启动项.png) + +#### 4.4.3 启动项设置错误的常见现象 + +| 现象 | 可能原因 | 解决方法 | +| --------------- | ------------- | ------------------- | +| 按 F5 运行的不是想要的项目 | 启动项选错 | 右键目标项目,设为启动项目 | +| 提示无法启动程序 | 没有生成 `.exe` | 检查项目类型是否为应用程序 | +| 静态库项目无法运行 | `.lib` 不能直接运行 | 设置主程序 `.exe` 项目为启动项 | +| 运行按钮是灰色 | 项目未加载或配置异常 | 重新加载项目,检查配置 | + +### 4.5 向解决方案添加项目 + +#### 4.5.1 添加项目的含义 + +解决方案可以管理一个项目,也可以管理多个项目。添加项目就是把新的项目加入到当前解决方案中,方便多个项目一起管理、编译和调试。 + +常见组合如下: + +| 组合方式 | 说明 | +| -------------- | ------------------ | +| 主程序项目 + 静态库项目 | 主程序调用自己写的 `.lib` 库 | +| 主程序项目 + 单元测试项目 | 一个项目写功能,一个项目写测试 | +| 多个模块项目 | 不同模块拆分成不同项目管理 | + +#### 4.5.2 添加新项目 + +操作步骤: + +1. 在 `解决方案资源管理器` 中,右键点击最上层的解决方案; + +2. 选择: + + ```text + 添加 -> 新建项目 + ``` + +3. 选择项目模板,例如: + + ```text + 空项目 + ``` + +4. 点击: + + ```text + 下一步 + ``` + +5. 输入新项目名称,例如: + + ```text + Math_Lib + ``` + +6. 点击: + + ```text + 创建 + ``` + +7. 创建完成后,解决方案下会出现新的项目。 + +![添加新项目](pictures/VS2019_005.png) + +#### 4.5.3 添加现有项目 + +如果磁盘中已经存在一个项目,可以把它添加到当前解决方案中。 + +操作步骤: + +1. 右键点击解决方案; + +2. 选择: + + ```text + 添加 -> 现有项目 + ``` + +3. 找到已有项目文件; + +4. 选择后缀为 `.vcxproj` 的文件; + +5. 点击: + + ```text + 打开 + ``` + +6. 该项目会被加入当前解决方案。 + +注意:添加现有项目不是复制代码,而是把已有项目引用到当前解决方案中。如果移动或删除原项目目录,解决方案可能会找不到该项目。 + +### 4.6 创建文件 + +#### 4.6.1 创建文件的含义 + +创建文件就是在项目中新增 `.c`、`.cpp`、`.h` 等代码文件。空项目刚创建完成后没有源文件,因此必须先添加源文件,项目才能正常编译生成。 + +常用文件类型如下: + +| 文件类型 | 后缀 | 作用 | +| ------- | ------ | ---------------- | +| C 源文件 | `.c` | 编写 C 语言函数实现 | +| C++ 源文件 | `.cpp` | 编写 C++ 函数实现 | +| 头文件 | `.h` | 编写函数声明、宏定义、结构体声明 | + +#### 4.6.2 创建源文件 + +操作步骤: + +1. 在 `解决方案资源管理器` 中找到当前项目; + +2. 右键点击: + + ```text + 源文件 + ``` + +3. 选择: + + ```text + 添加 -> 新建项 + ``` + +4. 选择: + + ```text + C++ 文件(.cpp) + ``` + +5. 输入文件名,例如: + + ```text + main.cpp + ``` + +6. 点击: + + ```text + 添加 + ``` + +7. 在 `main.cpp` 中编写测试代码。 + +示例代码: + +```cpp +#include + +int main() +{ + std::cout << "Hello Visual Studio 2019" << std::endl; + return 0; +} +``` + +![创建源文件](pictures/创建源文件.png) + +#### 4.6.3 创建头文件 + +操作步骤: + +1. 在 `解决方案资源管理器` 中右键点击: + + ```text + 头文件 + ``` + +2. 选择: + + ```text + 添加 -> 新建项 + ``` + +3. 选择: + + ```text + 头文件(.h) + ``` + +4. 输入文件名,例如: + + ```text + calc.h + ``` + +5. 点击: + + ```text + 添加 + ``` + +头文件示例: + +```cpp +#ifndef CALC_H +#define CALC_H + +int Add(int a, int b); + +#endif +``` + +对应源文件示例: + +```cpp +#include "calc.h" + +int Add(int a, int b) +{ + return a + b; +} +``` + +### 4.7 打开文件 + +#### 4.7.1 通过解决方案资源管理器打开文件 + +操作步骤: + +1. 在 `解决方案资源管理器` 中展开项目; + +2. 找到 `源文件` 或 `头文件`; + +3. 双击需要打开的文件; + +4. 文件会在中间编辑区域打开; + +5. 可以直接查看和修改代码。 + +#### 4.7.2 通过菜单打开文件 + +操作步骤: + +1. 点击菜单栏: + + ```text + 文件 -> 打开 -> 文件 + ``` + +2. 选择需要打开的 `.c`、`.cpp` 或 `.h` 文件; + +3. 点击: + + ```text + 打开 + ``` + +这种方式只是打开文件进行查看或编辑,不一定表示该文件已经加入当前项目。 + +#### 4.7.3 判断文件是否属于当前项目 + +可以通过以下方式判断文件是否已经加入项目: + +| 判断方式 | 说明 | +| --------------- | ------------------------- | +| 是否显示在解决方案资源管理器中 | 显示在项目目录下,一般表示已经加入项目 | +| 是否参与编译 | `.c/.cpp` 文件加入项目后,一般会参与编译 | +| 右键文件是否有属性 | 项目中的文件可以查看文件属性 | + +注意:仅仅把文件复制到工程文件夹下,不代表它已经加入 VS2019 项目。必须通过 `添加 -> 现有项` 或 `包括在项目中` 加入项目后,才会被项目管理。 + +### 4.8 包括文件和排除文件 + +#### 4.8.1 包括/排除文件的含义 + +在 VS2019 中,磁盘上的文件和项目中的文件不是完全一样的概念。 + +```text +磁盘上存在文件 ≠ 文件已经加入项目 +文件显示在项目中 ≈ 文件被项目管理 +源文件被项目管理后,通常会参与编译 +``` + +包括文件:把磁盘中的文件加入项目,让 VS2019 管理它。 + +排除文件:把文件从项目中移出,让它暂时不参与编译,但不删除磁盘上的真实文件。 + +#### 4.8.2 添加现有文件到项目 + +如果文件已经在磁盘上存在,可以通过以下方式加入项目。 + +操作步骤: + +1. 在 `解决方案资源管理器` 中右键点击项目或对应筛选器,例如 `源文件`; + +2. 选择: + + ```text + 添加 -> 现有项 + ``` + +3. 选择已有的 `.c`、`.cpp` 或 `.h` 文件; + +4. 点击: + + ```text + 添加 + ``` + +5. 文件出现在解决方案资源管理器中,表示已经加入项目。 + +![添加现有文件](pictures/VS2019_007_添加现有文件.png) + +#### 4.8.3 从项目中排除文件 + +操作步骤: + +1. 在 `解决方案资源管理器` 中找到需要排除的文件; + +2. 右键点击该文件; + +3. 选择: + + ```text + 从项目中排除 + ``` + +4. 文件会从项目视图中消失; + +5. 该文件不会再参与项目编译; + +6. 但是磁盘上的真实文件仍然存在。 + +适用场景: + +| 场景 | 说明 | +| ---------------- | ------------- | +| 某个 `.cpp` 文件暂时不用 | 排除后不参与编译 | +| 同名函数重复定义 | 可以先排除其中一个源文件 | +| 临时保留旧版本代码 | 文件留在磁盘,但不加入项目 | + +#### 4.8.4 重新包括被排除的文件 + +如果文件被排除后想重新加入项目,可以使用 `显示所有文件`。 + +操作步骤: + +1. 在 `解决方案资源管理器` 上方点击: + + ```text + 显示所有文件 + ``` + ![包括在项目中](pictures/VS2019.png) + +2. 找到被排除的文件; + +3. 此时文件图标一般会比较虚; + +4. 右键点击该文件; + +5. 选择: + + ```text + 包括在项目中 + ``` + +6. 文件重新加入项目,并可以参与编译。 + +![包括在项目中](pictures/VS2019_008_包括在项目中.png) + +#### 4.8.5 排除、移除、删除的区别 + +这三个操作容易混淆,需要重点区分。 + +| 操作 | 是否还在项目中 | 是否删除磁盘文件 | 是否参与编译 | 说明 | +| ------ | ------- | -------- | ------ | ----------------- | +| 从项目中排除 | 否 | 否 | 否 | 最安全,只是不让项目管理该文件 | +| 移除 | 否 | 通常不删除 | 否 | 从项目中移除引用,文件一般还在磁盘 | +| 删除 | 否 | 可能删除 | 否 | 风险最高,可能直接删除真实文件 | + +学习和验收时,如果只是想让某个文件不参与编译,优先使用 `从项目中排除`,不要直接删除文件。 + +### 4.9 工程创建部分验收要点 + +工程创建部分需要能够独立完成以下操作: + +1. 新建一个 VS2019 空项目; +2. 添加 `main.cpp` 文件,并写入简单测试代码; +3. 能够通过 `.sln` 打开已有工程; +4. 能够卸载项目和重新加载项目; +5. 能够把指定项目设置为启动项; +6. 能够向解决方案中添加新项目或现有项目; +7. 能够创建 `.cpp` 源文件和 `.h` 头文件; +8. 能够打开工程中的文件; +9. 能够把已有文件添加到项目; +10. 能够将文件从项目中排除,并重新包括到项目中; +11. 能够说明“排除、移除、删除”的区别。 + +工程创建部分的核心不是只会点“创建”,而是要理解: + +```text +解决方案负责管理多个项目; +项目负责管理代码文件和编译配置; +文件只有加入项目后,才会被项目管理和参与编译。 +``` + +## 5. 工程配置 + +### 5.1 打开项目属性页 + +大部分工程配置都在项目属性页中完成。 + +打开步骤: + +1. 在 `解决方案资源管理器` 中右键点击项目; + +2. 选择: + + ```text + 属性 + ``` + +3. 打开 `项目属性页`; + +4. 在顶部选择当前配置和平台; + +5. 在左侧选择需要修改的配置项。 + +![项目属性页](pictures/VS2019_004_项目属性页.png) + +属性页顶部一般有两个关键选项: + +```text +配置:Debug / Release / 所有配置 +平台:Win32 / x64 / 所有平台 +``` + +修改配置前一定要确认当前修改的是哪个配置和哪个平台,否则容易出现 Debug 能用、Release 不能用,或者 x64 能用、Win32 不能用的问题。 + +### 5.2 解决方案配置 + +解决方案配置用于选择当前工程的编译模式,常见有 `Debug` 和 `Release`。 + +| 配置 | 特点 | 使用场景 | +| ------- | ------------------ | ------- | +| Debug | 包含调试信息,优化较少,便于断点调试 | 开发和调试阶段 | +| Release | 优化较多,运行效率更高,调试信息较少 | 发布和交付阶段 | + +切换步骤: + +1. 在 VS 顶部工具栏找到配置下拉框; + + ![](pictures/解决方案配置.png) + +2. 选择: + + ```text + Debug + ``` + + 或: + + ```text + Release + ``` + +3. 重新生成项目。 + +也可以通过以下菜单打开配置管理器: + +```text +生成 -> 配置管理器 +``` + +![](pictures/配置管理器.png) + +在配置管理器中可以查看每个项目是否参与当前解决方案生成。 + +### 5.3 平台配置 + +平台配置用于选择程序生成的平台类型,常见有 `Win32` 和 `x64`。 + +| 平台 | 含义 | +| ----- | --------- | +| Win32 | 生成 32 位程序 | +| x64 | 生成 64 位程序 | + +切换步骤: + +1. 在 VS 顶部工具栏找到平台下拉框; + +2. 选择 `Win32` 或 `x64`; + +3. 如果没有目标平台,打开: + + ```text + 生成 -> 配置管理器 + ``` + +4. 在 `活动解决方案平台` 中选择或新建平台。 + +注意: + +* 程序、静态库、动态库的平台需要保持一致; +* x64 程序不能直接链接 Win32 的 `.lib`; +* 平台不一致时,容易出现链接错误。 + +![](pictures/平台配置.png) + +### 5.4 项目类型配置 + +项目类型决定工程最终生成什么文件。 + +配置路径: + +```text +项目属性 -> 配置属性 -> 常规 -> 配置类型 +``` + +常见配置类型如下: + +| 配置类型 | 生成文件 | 说明 | +| ---------- | ------ | -------------- | +| 应用程序(.exe) | `.exe` | 可以直接运行的程序 | +| 静态库(.lib) | `.lib` | 编译成库文件,供其他项目链接 | +| 动态库(.dll) | `.dll` | 运行时动态加载的库 | +| 生成文件 | 自定义 | 一般用于特殊构建流程 | + +设置步骤: + +1. 右键项目,选择 `属性`; + +2. 进入: + + ```text + 配置属性 -> 常规 + ``` + +3. 找到 `配置类型`; + +4. 根据需要选择 `应用程序(.exe)`、`静态库(.lib)` 或 `动态库(.dll)`; + + ![](pictures/项目类型配置.png) + +5. 点击 `应用`; + +6. 重新生成项目。 + +### 5.5 输出路径配置 + +输出路径用于设置编译生成文件的保存位置。 + +配置路径: + +```text +项目属性 -> 配置属性 -> 常规 +``` + +常见选项: + +| 选项 | 说明 | +| ------- | ------------------------------ | +| 输出目录 | `.exe`、`.lib`、`.dll` 等最终文件输出位置 | +| 中间目录 | `.obj`、临时编译文件输出位置 | +| 目标文件名 | 最终生成文件名称 | +| 目标文件扩展名 | 例如 `.exe`、`.lib`、`.dll` | + +![](pictures/输出路径配置.png) + +常用写法示例: + +```text +输出目录:$(SolutionDir)bin\$(Platform)\$(Configuration)\ +中间目录:$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\ +``` + +常用宏说明: + +| 宏 | 含义 | +| ------------------ | ----------------------- | +| `$(SolutionDir)` | 当前解决方案所在目录 | +| `$(ProjectDir)` | 当前项目所在目录 | +| `$(ProjectName)` | 当前项目名称 | +| `$(Configuration)` | 当前配置,例如 Debug 或 Release | +| `$(Platform)` | 当前平台,例如 Win32 或 x64 | + +配置输出路径可以让生成文件结构更清晰,避免 Debug、Release、Win32、x64 文件混在一起。 + +### 5.6 头文件路径配置 + +当代码中使用 `#include` 引用其他目录下的头文件时,需要配置头文件搜索路径。 + +配置路径: + +```text +项目属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录 +``` + +示例: + +```text +$(ProjectDir)include +$(SolutionDir)common\include +``` + +配置步骤: + +1. 右键项目,选择 `属性`; + +2. 进入: + + ```text + 配置属性 -> C/C++ -> 常规 + ``` + +3. 找到 `附加包含目录`; + +4. 点击右侧下拉按钮,选择 `编辑`; + +5. 添加头文件所在目录; + +6. 点击 `确定`; + +7. 重新生成项目。 + + ![](pictures/头文件路径配置.png) + +注意: + +* 配置的是目录,不是具体的 `.h` 文件; +* 如果头文件在 `include` 文件夹中,一般填写 `include` 文件夹路径; +* 如果报错 `无法打开包括文件`,优先检查这里。 + +### 5.7 源文件路径配置 + +源文件一般需要加入项目后才会参与编译。仅仅把 `.c` 或 `.cpp` 文件放到工程目录中,不一定会自动参与编译。 + +添加源文件的常用方法: + +```text +右键项目 -> 添加 -> 现有项 +``` + +然后选择需要加入的 `.c` 或 `.cpp` 文件。 + +也可以通过: + +```text +右键源文件 -> 添加 -> 新建项 +``` + +创建新的源文件。 + +注意: + +* 源文件必须包含在项目中,才会参与编译; +* 被 `从项目中排除` 的源文件不会参与编译; +* 如果函数已经写好但链接时报找不到函数,可能是对应 `.c/.cpp` 没有加入项目。 + +### 5.8 库文件路径配置 + +当项目需要调用 `.lib` 库文件时,需要配置库文件路径。 + +配置路径: + +```text +项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录 +``` + +示例: + +```text +$(SolutionDir)lib\$(Platform)\$(Configuration) +``` + +配置步骤: + +1. 右键项目,选择 `属性`; + +2. 进入: + + ```text + 配置属性 -> 链接器 -> 常规 + ``` + +3. 找到 `附加库目录`; + +4. 添加 `.lib` 文件所在目录; + +5. 点击 `应用`。 + +注意:这里配置的是 `.lib` 所在的文件夹路径,不是具体的 `.lib` 文件名。 + +### 5.9 调用库配置 + +调用库文件通常需要完成三件事:包含头文件、配置库目录、添加库文件名。 + +#### 5.9.1 包含头文件 + +在代码中包含库对应的头文件: + +```cpp +#include "xxx.h" +``` + +同时在 `附加包含目录` 中添加头文件所在路径。 + +#### 5.9.2 配置库目录 + +配置路径: + +```text +项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录 +``` + +添加 `.lib` 文件所在目录。 + +#### 5.9.3 添加库文件名 + +配置路径: + +```text +项目属性 -> 配置属性 -> 链接器 -> 输入 -> 附加依赖项 +``` + +示例: + +```text +my_math.lib +user_driver.lib +``` + +完整流程如下: + +```text +头文件路径 -> 附加包含目录 +库文件路径 -> 附加库目录 +库文件名称 -> 附加依赖项 +``` + +如果是动态库 `.dll`,除了配置 `.lib` 参与链接外,还要保证运行时能找到 `.dll` 文件。常见做法是把 `.dll` 放到 `.exe` 同级目录下。 + +### 5.10 宏定义 + +宏定义常用于控制编译开关、区分 Debug/Release、打开或关闭某些功能。 + +配置路径: + +```text +项目属性 -> 配置属性 -> C/C++ -> 预处理器 -> 预处理器定义 +``` + +示例: + +```text +DEBUG +USE_CAN +ENABLE_LOG +_CRT_SECURE_NO_WARNINGS +``` + +![](pictures/宏定义.png) + +代码中可以这样使用: + +```cpp +#ifdef ENABLE_LOG +printf("log enable\n"); +#endif +``` + +常见用途: + +| 宏定义 | 作用 | +| ------------------------- | ----------------- | +| `DEBUG` | 表示当前为调试版本 | +| `NDEBUG` | 表示关闭 assert 等调试功能 | +| `_CRT_SECURE_NO_WARNINGS` | 关闭部分 C 标准库安全警告 | +| `USE_XXX` | 控制某个模块是否参与编译 | + +注意: + +* 多个宏之间用分号分隔; +* 不同配置下宏定义可能不同; +* 如果 Debug 正常、Release 异常,要检查两个配置下的宏定义是否一致。 + +### 5.11 运行库配置 + +运行库决定程序使用哪种 C/C++ 运行时库。 + +配置路径: + +```text +项目属性 -> 配置属性 -> C/C++ -> 代码生成 -> 运行库 +``` + +常见选项如下: + +| 选项 | 含义 | 常见场景 | +| ---------------- | ------------------ | ----------- | +| 多线程 DLL `/MD` | 使用动态运行库,Release 常用 | 发布版本 | +| 多线程调试 DLL `/MDd` | 使用动态调试运行库,Debug 常用 | 调试版本 | +| 多线程 `/MT` | 使用静态运行库,Release 可用 | 不想依赖运行库 DLL | +| 多线程调试 `/MTd` | 使用静态调试运行库,Debug 可用 | 调试版本 | + +![](pictures/运行库配置.png) + +配置建议: + +1. Debug 配置一般使用 `/MDd` 或 `/MTd`; +2. Release 配置一般使用 `/MD` 或 `/MT`; +3. 主程序和静态库项目的运行库配置尽量保持一致; +4. 如果运行库不一致,可能出现链接冲突或运行异常。 + +### 5.12 安全检查 + +安全检查用于增强程序运行时的安全性,例如检测部分缓冲区溢出问题。 + +常见配置位置: + +```text +项目属性 -> 配置属性 -> C/C++ -> 代码生成 -> 安全检查 +``` + +![](pictures/安全检查.png) + +常见选项: + +| 选项 | 说明 | +| ------------- | ------------ | +| 启用安全检查 `/GS` | 编译器加入栈安全检查代码 | +| 禁用安全检查 `/GS-` | 不加入该检查代码 | + +一般情况下建议保持默认启用,不建议随意关闭。只有在明确知道关闭原因,并且项目要求关闭时,才进行修改。 + +## 6. 工程生成和运行 + +### 6.1 生成解决方案 + +生成解决方案会编译当前解决方案中参与生成的项目。 + +操作方法: + +```text +生成 -> 生成解决方案 +``` + +快捷键: + +```text +Ctrl + Shift + B +``` + +### 6.2 重新生成解决方案 + +重新生成会先清理旧的中间文件,再重新编译整个解决方案。 + +操作路径: + +```text +生成 -> 重新生成解决方案 +``` + +适合场景: + +* 修改了大量工程配置; +* 编译结果异常; +* 怀疑中间文件没有更新; +* 从别的电脑拷贝工程后首次编译。 + +### 6.3 清理解决方案 + +清理解决方案会删除编译生成的中间文件和输出文件。 + +操作路径: + +```text +生成 -> 清理解决方案 +``` + +常用于重新编译前清空旧文件。 + +### 6.4 运行程序 + +常用运行方式如下: + +| 操作 | 快捷键 | 说明 | +| ------- | ------------------- | -------------- | +| 开始调试 | `F5` | 运行程序并进入调试状态 | +| 开始执行不调试 | `Ctrl + F5` | 直接运行程序,不进入断点调试 | +| 停止调试 | `Shift + F5` | 停止当前调试 | +| 重新启动 | `Ctrl + Shift + F5` | 重新运行当前调试程序 | + +调试阶段常用 `F5`,普通运行查看输出时可以使用 `Ctrl + F5`。 + +## 7. 工程调试 + +### 7.1 断点创建 + +断点用于让程序运行到指定代码行时暂停,方便查看变量、内存和函数调用关系。 + +创建断点的方法: + +方法一: + +1. 打开源文件; +2. 将光标放到需要暂停的代码行; +3. 按快捷键: + + ```text + F9 + ``` + +方法二: + +1. 在代码行最左侧灰色区域点击鼠标; +2. 出现红色圆点,表示断点创建成功。 + +![断点调试](pictures/VS2019_005_断点调试.png) + +### 7.2 断点删除 + +删除单个断点: + +1. 找到有红色圆点的代码行; +2. 再次点击红色圆点; +3. 红点消失,断点删除。 + +也可以选中断点所在行,按: + +```text +F9 +``` + +删除所有断点: + +![](pictures/删除所有断点.png) + +```text +调试 -> 删除所有断点 +``` + +### 7.3 断点禁用 + +禁用断点表示暂时不让断点生效,但保留断点位置。 + +操作步骤: + +1. 右键点击断点红点; + +2. 选择: + + ![](pictures/禁用断点.png) + + ```text + 禁用断点 + ``` + +3. 断点图标会发生变化,表示该断点当前不生效。 + + ![](pictures/空心断点.png) + +适合场景: + +* 当前暂时不想停在该位置; +* 后面可能还要继续使用该断点; +* 不想删除后再重新找位置。 + +### 7.4 断点启用 + +启用断点表示让被禁用的断点重新生效。 + +操作步骤: + +1. 右键点击被禁用的断点; + +2. 选择: + + ```text + 启用断点 + ``` + +3. 程序再次运行到该行时会暂停。 + + +### 7.5 条件断点 + +条件断点表示只有满足指定条件时,程序才会暂停。普通断点是程序运行到该行就暂停,而条件断点是在普通断点的基础上增加判断条件,只有条件成立时才会真正停下来。 + +![条件断点设置界面](pictures/右击条件断点.png) + +条件断点适合循环次数很多,但只想观察某一次特殊情况的场景。例如循环执行 1000 次,但只想在 `i == 500` 时暂停,就可以使用条件断点。 + +设置步骤: + +1. 先在需要暂停的代码行创建普通断点; + +2. 右键点击断点红点; + +3. 在右键菜单中选择: + + ```text + 条件 + ``` + +4. 在弹出的条件断点设置窗口中输入条件表达式,例如: + + ```cpp + i == 10 + ``` + + 或: + + ```cpp + count > 100 + ``` + +5. 设置完成后继续运行程序; + + ![](pictures/条件设置.png) + +6. 程序运行到该断点位置时,只有条件满足才会暂停。 + +示例代码: + +```cpp +for (int i = 0; i < 1000; i++) +{ + sum += i; +} +``` + +如果只想在 `i == 500` 时暂停,可以在循环内部设置条件断点: + +```cpp +i == 500 +``` + +这样程序不会在每一次循环时都暂停,而是只会在 `i` 等于 500 时暂停,方便观察特定情况下变量的值。 + +### 7.6 监视窗口 + +监视窗口用于查看变量、表达式、数组元素、指针指向的值。程序运行到断点暂停后,可以通过监视窗口观察变量当前的数值变化。 + +![监视窗口查看变量](pictures/监视窗口2.png) + +打开路径: + +```text +调试 -> 窗口 -> 监视 -> 监视 1 +``` + +![监视窗口查看变量](pictures/监视窗口.png) + +使用步骤: + +1. 程序运行到断点后暂停; +2. 打开监视窗口; +3. 在监视窗口中输入变量名或表达式; +4. 查看变量当前值; +5. 单步执行程序,观察变量值是否发生变化。 + +常见输入内容如下: + +```text +a +a + b +arr[0] +*p +&buffer[0] +``` + +说明: + +| 输入内容 | 含义 | +| ------------ | ---------------- | +| `a` | 查看变量 `a` 的值 | +| `a + b` | 查看表达式 `a + b` 的值 | +| `arr[0]` | 查看数组第 0 个元素 | +| `*p` | 查看指针 `p` 指向的内容 | +| `&buffer[0]` | 查看数组首元素地址 | + +监视窗口是调试时最常用的窗口之一,适合用来观察变量值是否符合预期。 + +### 7.7 内存窗口 + +内存窗口用于查看某个地址开始的一段内存内容。相比监视窗口,内存窗口更偏底层,可以直接观察内存地址中的数据。 + +![内存窗口查看数据](pictures/内存窗口查看数据.png) + +打开路径: + +```text +调试 -> 窗口 -> 内存 -> 内存 1 +``` + +使用步骤: + +1. 程序运行到断点后暂停; + +2. 打开内存窗口; + +3. 在内存窗口地址栏中输入变量地址,例如: + + ```cpp + &p + ``` + + 或: + + ```cpp + &buffer[0] + ``` + +4. 查看该地址开始的一段内存数据。 + +内存窗口常用于查看数组、结构体、指针、通信缓冲区等内容。 + +例如有如下数组: + +```cpp +unsigned char buffer[4] = {0x11, 0x22, 0x33, 0x44}; +``` + +可以在内存窗口中输入: + +```cpp +&buffer[0] +``` + +然后观察数组在内存中的实际存放情况。 + +注意:内存窗口查看的是地址中的原始数据,适合排查指针、数组越界、通信数据缓存等问题。 + +### 7.8 线程窗口 + +线程窗口用于查看当前程序中的线程信息。当程序是多线程程序时,可以通过线程窗口查看每个线程的执行位置和状态。 + +![线程窗口内容](pictures/线程窗口内容.png) + +打开路径: + +```text +调试 -> 窗口 -> 线程 +``` + +线程窗口可以查看以下内容: + +| 内容 | 说明 | +| ----- | --------------- | +| 线程 ID | 当前线程编号 | +| 线程名称 | 线程名称或系统显示名称 | +| 当前位置 | 当前线程执行到的函数或代码位置 | +| 状态 | 线程当前运行或暂停状态 | + +当程序运行到断点暂停时,如果程序中存在多个线程,可以在线程窗口中切换不同线程,查看不同线程当前执行到的位置。 + +线程窗口常用于分析: + +1. 当前程序有几个线程; +2. 哪个线程正在执行目标代码; +3. 多线程程序是否出现线程卡死; +4. 多线程调试时切换不同线程观察执行状态。 + +### 7.9 调用堆栈窗口 + +调用堆栈窗口用于查看函数调用关系。程序运行到断点暂停时,调用堆栈可以显示当前函数是被哪些函数一级一级调用进来的。 + +![调用堆栈窗口](pictures/调用堆栈窗口.png) + +打开路径: + +```text +调试 -> 窗口 -> 调用堆栈 +``` + +例如程序调用关系如下: + +```text +main -> Motor_Init -> Driver_Init -> GPIO_Init +``` + +当程序停在 `GPIO_Init` 函数中时,调用堆栈窗口可以看到它是从 `main` 函数开始,经过 `Motor_Init`、`Driver_Init`,最后进入 `GPIO_Init` 的。 + +调用堆栈常用于分析: + +1. 当前函数是从哪里被调用的; +2. 程序为什么会进入某个函数; +3. 程序异常时崩溃前的调用路径; +4. 多层函数嵌套时的执行关系。 + +调用堆栈对排查程序异常非常重要。比如程序进入了错误处理函数,可以通过调用堆栈向上查找,是哪个函数调用导致的错误。 + +### 7.10 单步调试 + +单步调试用于逐行分析程序执行过程。程序运行到断点暂停后,可以通过单步调试观察程序每一行代码的执行情况。 + +![单步调试按钮](pictures/单步调试按钮.png) + +常用调试操作如下: + +| 操作 | 快捷键 | 说明 | +| ---- | ------------------- | ------------------------- | +| 全速运行 | `F5` | 从当前位置继续运行,直到遇到下一个断点或程序结束 | +| 重新运行 | `Ctrl + Shift + F5` | 停止当前调试并重新启动 | +| 逐过程 | `F10` | 执行当前行,如果当前行是函数调用,则不进入函数内部 | +| 逐语句 | `F11` | 执行当前行,如果当前行是函数调用,则进入函数内部 | +| 跳出 | `Shift + F11` | 从当前函数执行完并返回上一层函数 | + +逐过程和逐语句区别如下: + +| 操作 | 是否进入函数内部 | 使用场景 | +| --------- | -------- | ------------ | +| 逐过程 `F10` | 不进入 | 只关心函数调用结果 | +| 逐语句 `F11` | 进入 | 需要查看函数内部执行过程 | + +示例代码: + +```cpp +int add(int a, int b) +{ + return a + b; +} + +int main(void) +{ + int ret = add(1, 2); + return 0; +} +``` + +当程序停在下面这一行时: + +```cpp +int ret = add(1, 2); +``` + +如果按 `F10`,程序会直接执行完 `add` 函数,不进入函数内部。 + +如果按 `F11`,程序会进入 `add` 函数内部,可以继续观察: + +```cpp +return a + b; +``` + +简单理解: + +```text +F10:不进函数,只看结果 +F11:进入函数,看内部细节 +``` + +## 8. 常见问题和排查方法总结 + +在 VS2019 使用过程中,常见问题主要集中在编译错误、链接错误、配置不一致和文件未加入项目等方面。排查问题时,应先判断错误发生在编译阶段还是链接阶段。 + +### 8.1 找不到头文件 + +常见报错: + +```text +无法打开包括文件: “xxx.h”: No such file or directory +``` + +该问题一般属于编译阶段错误,说明编译器在当前搜索路径中没有找到对应的头文件。 + +常见原因如下: + +1. 头文件本身不存在; +2. 头文件路径写错; +3. 头文件没有放在工程目录中; +4. `附加包含目录` 没有配置; +5. 当前 Debug/Release 或 Win32/x64 平台下没有配置该路径。 + +排查思路: + +1. 先确认磁盘中确实存在该 `.h` 文件; +2. 检查 `#include` 中的文件名是否拼写正确; +3. 检查项目属性中的头文件路径配置: + + ```text + 项目属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录 + ``` + +4. 确认当前修改的是正确的配置和平台; +5. 重新生成解决方案。 + +总结: + +```text +找不到 .h 文件,优先检查 附加包含目录。 +``` + +### 8.2 找不到库文件 + +常见报错: + +```text +LINK : fatal error LNK1104: 无法打开文件 “xxx.lib” +``` + +该问题一般属于链接阶段错误,说明链接器没有找到需要链接的 `.lib` 文件。 + +常见原因如下: + +1. `.lib` 文件不存在; +2. `.lib` 文件还没有生成; +3. `附加库目录` 配置错误; +4. `附加依赖项` 中库文件名写错; +5. Debug/Release 或 Win32/x64 平台不一致。 + +排查思路: + +1. 确认 `.lib` 文件真实存在; +2. 检查库文件所在目录是否配置正确: + + ```text + 项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录 + ``` + +3. 检查库文件名称是否填写正确: + + ```text + 项目属性 -> 配置属性 -> 链接器 -> 输入 -> 附加依赖项 + ``` + +4. 确认主程序和库文件的平台一致; +5. 如果是自建库,应先生成库项目,再生成主程序项目。 + +总结: + +```text +找不到 .lib 文件,优先检查 附加库目录 和 附加依赖项。 +``` + +### 8.3 无法解析的外部符号 + +常见报错: + +```text +error LNK2019: 无法解析的外部符号 +``` + +该问题属于链接阶段错误,通常说明函数已经被声明或调用,但是链接器没有找到对应的函数实现。 + +常见原因如下: + +1. 函数只有声明,没有实现; +2. 实现函数的 `.c` 或 `.cpp` 文件没有加入项目; +3. 调用了库函数,但没有链接对应的 `.lib` 文件; +4. C 和 C++ 混合编译时,函数名修饰不一致; +5. Debug/Release 或 Win32/x64 链接了错误版本的库。 + +排查思路: + +1. 检查函数是否真的有实现; +2. 检查实现函数的源文件是否已经加入项目; +3. 检查库文件路径和库文件名是否配置正确; +4. 如果 C 函数被 C++ 调用,可以检查是否需要: + + ```cpp + extern "C" + { + #include "xxx.h" + } + ``` + +5. 清理后重新生成解决方案。 + +总结: + +```text +LNK2019 通常不是语法问题,而是链接阶段找不到函数实现。 +``` + +### 8.4 Debug 正常但 Release 异常 + +Debug 正常但 Release 异常,通常说明两个配置下的工程属性不一致,或者 Release 优化后暴露了代码中的隐藏问题。 + +常见原因如下: + +1. Debug 和 Release 的宏定义不同; +2. Debug 和 Release 的运行库配置不同; +3. Release 开启优化后,未初始化变量等问题暴露; +4. Debug 和 Release 的输出路径或库路径不同; +5. Release 链接的库版本不正确。 + +排查思路: + +1. 对比 Debug 和 Release 的项目属性; +2. 检查 `预处理器定义`; +3. 检查 `运行库`; +4. 检查 `附加包含目录`、`附加库目录`、`附加依赖项`; +5. 清理后重新生成。 + +总结: + +```text +Debug 正常但 Release 异常,优先对比两种配置下的项目属性。 +``` + +### 8.5 x64 正常但 Win32 异常 + +x64 正常但 Win32 异常,通常说明不同平台下的配置没有保持一致,或者链接了错误平台的库文件。 + +常见原因如下: + +1. 只配置了 x64,没有配置 Win32; +2. 使用了 x64 版本的 `.lib` 去链接 Win32 程序; +3. 输出路径中平台目录混乱; +4. 第三方库没有提供 Win32 版本; +5. 当前活动平台选择错误。 + +排查思路: + +1. 打开项目属性页,把平台切换到 Win32; +2. 检查 Win32 下的所有路径配置; +3. 确认 Win32 使用的是 Win32 版本库; +4. 检查输出目录和中间目录是否区分平台; +5. 重新生成解决方案。 + +总结: + +```text +x64 和 Win32 是不同平台,库文件和工程配置需要保持一致。 +``` + +### 8.6 常见问题对应关系总结 + +| 问题现象 | 所属阶段 | 优先检查内容 | +| ------------------------- | ------------ | ---------------------------------------- | +| 找不到 `.h` 文件 | 编译阶段 | 附加包含目录、头文件路径 | +| 找不到 `.lib` 文件 | 链接阶段 | 附加库目录、附加依赖项 | +| 无法解析外部符号 | 链接阶段 | 函数实现、源文件是否加入项目、库是否链接 | +| Debug 正常但 Release 异常 | 配置问题 | Debug/Release 配置差异 | +| x64 正常但 Win32 异常 | 平台问题 | Win32/x64 配置和库平台是否一致 | +| 写了源文件但不编译 | 工程管理问题 | 文件是否被包括在项目中 | +| 按 F5 运行错误项目 | 启动项问题 | 是否设置正确启动项 | + +## 9. 学习练习总结 + +本章节用于总结 VS2019 基础学习过程中需要完成的练习内容。通过练习,应能够掌握项目创建、文件添加、程序生成、程序运行和基本调试操作。 + +### 9.1 练习一:创建控制台项目 + +练习目标: + +1. 熟悉 VS2019 创建项目流程; +2. 理解解决方案和项目之间的关系; +3. 能够创建一个可以运行的控制台程序; +4. 掌握生成和运行程序的方法。 + +练习要求: + +1. 创建一个 VS2019 控制台项目; +2. 添加 `main.cpp` 文件; +3. 编写简单打印程序; +4. 使用 `Ctrl + Shift + B` 生成解决方案; +5. 使用 `Ctrl + F5` 运行程序。 + +示例代码: + +```cpp +#include + +int main(void) +{ + printf("Hello Visual Studio 2019!\n"); + return 0; +} +``` + +运行后控制台应输出: + +```text +Hello Visual Studio 2019! +``` + +### 9.2 练习二:添加头文件和源文件 + +练习目标: + +1. 掌握头文件和源文件的创建方法; +2. 理解函数声明和函数实现的区别; +3. 能够在主程序中调用自己编写的函数; +4. 理解源文件必须加入项目后才会参与编译。 + +练习要求: + +1. 新建 `math_user.h`; +2. 新建 `math_user.cpp`; +3. 在头文件中声明函数; +4. 在源文件中实现函数; +5. 在 `main.cpp` 中调用函数; +6. 生成并运行程序。 + +`math_user.h`: + +```cpp +#ifndef MATH_USER_H +#define MATH_USER_H + +int add(int a, int b); + +#endif +``` + +`math_user.cpp`: + +```cpp +#include "math_user.h" + +int add(int a, int b) +{ + return a + b; +} +``` + +`main.cpp`: + +```cpp +#include +#include "math_user.h" + +int main(void) +{ + int ret = add(1, 2); + printf("ret = %d\n", ret); + return 0; +} +``` + +运行后应输出: + +```text +ret = 3 +``` + +### 9.3 练习三:断点调试 + +练习目标: + +1. 掌握断点创建方法; +2. 能够使用 `F5` 开始调试; +3. 能够使用 `F10` 和 `F11` 进行单步调试; +4. 能够通过监视窗口查看变量值; +5. 能够通过调用堆栈查看函数调用关系。 + +练习要求: + +1. 在 `ret = add(1, 2);` 这一行设置断点; +2. 按 `F5` 开始调试; +3. 使用 `F10` 逐过程调试; +4. 使用 `F11` 逐语句进入函数; +5. 打开监视窗口查看 `ret` 的值; +6. 打开调用堆栈窗口查看函数调用关系。 + +调试时重点观察: + +```text +F10 不进入函数内部; +F11 会进入函数内部。 +``` + +### 9.4 练习四:条件断点 + +练习目标: + +1. 掌握条件断点的设置方法; +2. 理解普通断点和条件断点的区别; +3. 能够让程序只在满足指定条件时暂停; +4. 能够配合监视窗口观察变量变化。 + +练习要求: + +1. 编写一个 `for` 循环; +2. 在循环内部设置断点; +3. 设置条件断点 `i == 5`; +4. 运行程序,观察程序是否只在 `i` 等于 5 时暂停。 + +示例代码: + +```cpp +#include + +int main(void) +{ + int sum = 0; + + for (int i = 0; i < 10; i++) + { + sum += i; + } + + printf("sum = %d\n", sum); + return 0; +} +``` + +条件表达式: + +```cpp +i == 5 +``` + +运行到条件断点时,可以在监视窗口中查看 `i` 和 `sum` 的值。 + +## 10. 验收重点总结 + +VS2019 基础操作验收时,应重点掌握工程创建、工程配置、工程调试和常见错误排查方法。验收时不仅要会操作菜单,还要理解每个配置项的作用。 + +### 10.1 工程创建验收重点 + +| 分类 | 必须掌握内容 | +| ------------- | ------------------------------------ | +| 创建项目 | 能够创建 VS2019 空项目或控制台项目 | +| 打开项目 | 能够通过 `.sln` 打开完整工程 | +| 加载/卸载项目 | 能够卸载项目并重新加载项目 | +| 设置启动项 | 能够设置正确的启动项目 | +| 添加项目 | 能够向解决方案中添加新项目或现有项目 | +| 文件管理 | 能够创建、打开、包括和排除文件 | + +### 10.2 工程配置验收重点 + +| 分类 | 必须掌握内容 | +| ------------ | ---------------------------------------- | +| 解决方案配置 | 理解 Debug 和 Release 的区别 | +| 平台配置 | 理解 Win32 和 x64 的区别 | +| 项目类型 | 理解 `.exe`、`.lib`、`.dll` 的区别 | +| 输出路径 | 能够配置输出目录和中间目录 | +| 头文件路径 | 能够配置附加包含目录 | +| 库文件路径 | 能够配置附加库目录 | +| 调用库 | 能够配置附加依赖项 | +| 宏定义 | 能够配置预处理器定义 | +| 运行库 | 理解 `/MD`、`/MDd`、`/MT`、`/MTd` 的含义 | +| 安全检查 | 了解安全检查配置的作用 | + +### 10.3 工程调试验收重点 + +| 分类 | 必须掌握内容 | +| -------- | ------------------------------------- | +| 断点 | 创建、删除、启用、禁用断点 | +| 条件断点 | 设置满足条件才暂停的断点 | +| 监视窗口 | 查看变量、表达式、数组和指针 | +| 内存窗口 | 查看指定地址的内存内容 | +| 线程窗口 | 查看多线程程序中的线程状态 | +| 调用堆栈 | 查看函数调用关系 | +| 单步调试 | 掌握 F5、F10、F11、Shift + F11 等操作 | + +### 10.4 常见错误排查重点 + +| 问题 | 优先检查内容 | +| ---------------- | ---------------------------------- | +| 找不到 `.h` | 附加包含目录 | +| 找不到 `.lib` | 附加库目录、附加依赖项 | +| 函数无法解析 | 源文件是否加入项目、库是否正确链接 | +| 程序运行不对 | 启动项、Debug/Release 配置 | +| 平台链接错误 | Win32/x64 是否一致 | +| 文件写了但不编译 | 是否被包括在项目中 | + +## 11. 快捷键汇总 + +VS2019 中常用快捷键可以提高工程生成、运行和调试效率。学习时应重点记住生成、运行和单步调试相关快捷键。 + +| 功能 | 快捷键 | +| -------------- | ------------------- | +| 生成解决方案 | `Ctrl + Shift + B` | +| 开始调试 | `F5` | +| 开始执行不调试 | `Ctrl + F5` | +| 停止调试 | `Shift + F5` | +| 重新启动调试 | `Ctrl + Shift + F5` | +| 设置/取消断点 | `F9` | +| 逐过程 | `F10` | +| 逐语句 | `F11` | +| 跳出函数 | `Shift + F11` | +| 查找 | `Ctrl + F` | +| 替换 | `Ctrl + H` | +| 保存当前文件 | `Ctrl + S` | +| 全部保存 | `Ctrl + Shift + S` | + +常用调试快捷键可以简单记为: + +```text +F5:继续运行 +F9:设置或取消断点 +F10:逐过程,不进入函数 +F11:逐语句,进入函数 +Shift + F11:跳出当前函数 +``` + +## 12. 学习结论 + +通过本次学习,掌握了 Visual Studio 2019 的基本工程创建、文件管理、工程配置和调试方法。VS2019 不只是代码编辑器,更重要的是它通过解决方案和项目来管理编译、链接和调试流程。 + +在实际使用中,需要重点关注以下几点: + +1. 修改配置前先确认当前是 Debug 还是 Release,是 Win32 还是 x64; +2. 解决方案用于管理项目,项目用于管理文件和编译配置; +3. 源文件必须加入项目后才会参与编译; +4. 头文件路径、库文件路径、库文件名是三个不同配置,不能混淆; +5. 多项目工程中要正确设置启动项; +6. 主程序和库文件的平台配置需要保持一致; +7. 调试时要熟练使用断点、监视窗口、内存窗口和调用堆栈窗口; +8. 遇到编译或链接错误时,先判断错误属于编译阶段还是链接阶段。 + +总结来说,VS2019 的学习重点不只是会点击菜单,而是要理解: + +```text +工程如何创建; +文件如何加入项目; +配置如何影响编译和链接; +调试工具如何帮助定位问题。 +``` + +掌握这些基础操作后,后续学习静态库生成与使用、单元测试等内容会更加容易。 \ No newline at end of file diff --git a/yuwenhao/VisualStudio/pictures/11.png b/yuwenhao/VisualStudio/pictures/11.png new file mode 100644 index 0000000..f4d6cd8 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/11.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019.png b/yuwenhao/VisualStudio/pictures/VS2019.png new file mode 100644 index 0000000..891b490 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_002.png b/yuwenhao/VisualStudio/pictures/VS2019_002.png new file mode 100644 index 0000000..7c9de1a Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_002.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_002_创建项目.png b/yuwenhao/VisualStudio/pictures/VS2019_002_创建项目.png new file mode 100644 index 0000000..db629b4 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_002_创建项目.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_003_卸载项目.png b/yuwenhao/VisualStudio/pictures/VS2019_003_卸载项目.png new file mode 100644 index 0000000..52db259 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_003_卸载项目.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_004_项目属性页.png b/yuwenhao/VisualStudio/pictures/VS2019_004_项目属性页.png new file mode 100644 index 0000000..385205d Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_004_项目属性页.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_005.png b/yuwenhao/VisualStudio/pictures/VS2019_005.png new file mode 100644 index 0000000..a7550ec Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_005.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_005_断点调试.png b/yuwenhao/VisualStudio/pictures/VS2019_005_断点调试.png new file mode 100644 index 0000000..8c3ece1 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_005_断点调试.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_007_添加现有文件.png b/yuwenhao/VisualStudio/pictures/VS2019_007_添加现有文件.png new file mode 100644 index 0000000..566be55 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_007_添加现有文件.png differ diff --git a/yuwenhao/VisualStudio/pictures/VS2019_008_包括在项目中.png b/yuwenhao/VisualStudio/pictures/VS2019_008_包括在项目中.png new file mode 100644 index 0000000..59ac07d Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/VS2019_008_包括在项目中.png differ diff --git a/yuwenhao/VisualStudio/pictures/内存窗口查看数据.png b/yuwenhao/VisualStudio/pictures/内存窗口查看数据.png new file mode 100644 index 0000000..c9d20f8 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/内存窗口查看数据.png differ diff --git a/yuwenhao/VisualStudio/pictures/创建源文件.png b/yuwenhao/VisualStudio/pictures/创建源文件.png new file mode 100644 index 0000000..935ad46 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/创建源文件.png differ diff --git a/yuwenhao/VisualStudio/pictures/删除所有断点.png b/yuwenhao/VisualStudio/pictures/删除所有断点.png new file mode 100644 index 0000000..6201f54 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/删除所有断点.png differ diff --git a/yuwenhao/VisualStudio/pictures/单步调试按钮.png b/yuwenhao/VisualStudio/pictures/单步调试按钮.png new file mode 100644 index 0000000..8754898 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/单步调试按钮.png differ diff --git a/yuwenhao/VisualStudio/pictures/右击条件断点.png b/yuwenhao/VisualStudio/pictures/右击条件断点.png new file mode 100644 index 0000000..bdb6b69 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/右击条件断点.png differ diff --git a/yuwenhao/VisualStudio/pictures/头文件路径配置.png b/yuwenhao/VisualStudio/pictures/头文件路径配置.png new file mode 100644 index 0000000..12d1ae5 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/头文件路径配置.png differ diff --git a/yuwenhao/VisualStudio/pictures/安全检查.png b/yuwenhao/VisualStudio/pictures/安全检查.png new file mode 100644 index 0000000..d292786 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/安全检查.png differ diff --git a/yuwenhao/VisualStudio/pictures/宏定义.png b/yuwenhao/VisualStudio/pictures/宏定义.png new file mode 100644 index 0000000..4a4c616 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/宏定义.png differ diff --git a/yuwenhao/VisualStudio/pictures/平台配置.png b/yuwenhao/VisualStudio/pictures/平台配置.png new file mode 100644 index 0000000..2aa7695 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/平台配置.png differ diff --git a/yuwenhao/VisualStudio/pictures/条件设置.png b/yuwenhao/VisualStudio/pictures/条件设置.png new file mode 100644 index 0000000..441d44b Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/条件设置.png differ diff --git a/yuwenhao/VisualStudio/pictures/监视窗口.png b/yuwenhao/VisualStudio/pictures/监视窗口.png new file mode 100644 index 0000000..b1734c1 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/监视窗口.png differ diff --git a/yuwenhao/VisualStudio/pictures/监视窗口2.png b/yuwenhao/VisualStudio/pictures/监视窗口2.png new file mode 100644 index 0000000..f23e7fb Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/监视窗口2.png differ diff --git a/yuwenhao/VisualStudio/pictures/禁用断点.png b/yuwenhao/VisualStudio/pictures/禁用断点.png new file mode 100644 index 0000000..2cca288 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/禁用断点.png differ diff --git a/yuwenhao/VisualStudio/pictures/空心断点.png b/yuwenhao/VisualStudio/pictures/空心断点.png new file mode 100644 index 0000000..88e63bf Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/空心断点.png differ diff --git a/yuwenhao/VisualStudio/pictures/线程窗口内容.png b/yuwenhao/VisualStudio/pictures/线程窗口内容.png new file mode 100644 index 0000000..76da15a Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/线程窗口内容.png differ diff --git a/yuwenhao/VisualStudio/pictures/解决方案配置.png b/yuwenhao/VisualStudio/pictures/解决方案配置.png new file mode 100644 index 0000000..7decd9e Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/解决方案配置.png differ diff --git a/yuwenhao/VisualStudio/pictures/设置启动项.png b/yuwenhao/VisualStudio/pictures/设置启动项.png new file mode 100644 index 0000000..846bf6b Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/设置启动项.png differ diff --git a/yuwenhao/VisualStudio/pictures/调用堆栈窗口.png b/yuwenhao/VisualStudio/pictures/调用堆栈窗口.png new file mode 100644 index 0000000..3e9ad3b Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/调用堆栈窗口.png differ diff --git a/yuwenhao/VisualStudio/pictures/输出路径配置.png b/yuwenhao/VisualStudio/pictures/输出路径配置.png new file mode 100644 index 0000000..c3a8b13 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/输出路径配置.png differ diff --git a/yuwenhao/VisualStudio/pictures/运行库配置.png b/yuwenhao/VisualStudio/pictures/运行库配置.png new file mode 100644 index 0000000..da4398f Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/运行库配置.png differ diff --git a/yuwenhao/VisualStudio/pictures/配置管理器.png b/yuwenhao/VisualStudio/pictures/配置管理器.png new file mode 100644 index 0000000..2203a48 Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/配置管理器.png differ diff --git a/yuwenhao/VisualStudio/pictures/重新加载项目.png b/yuwenhao/VisualStudio/pictures/重新加载项目.png new file mode 100644 index 0000000..8bab0fd Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/重新加载项目.png differ diff --git a/yuwenhao/VisualStudio/pictures/项目类型配置.png b/yuwenhao/VisualStudio/pictures/项目类型配置.png new file mode 100644 index 0000000..26c226a Binary files /dev/null and b/yuwenhao/VisualStudio/pictures/项目类型配置.png differ