好像这个应该在 2018 年就写的……
最近有不少大一小朋友们又开始了饱受 Dev C++ 折磨的 C 语言课程。有一部分先进的小朋友选择使用 Visual Studio 进行编程,不过还是在 scanf
和 scanf_s
之间挣扎了一段时间。如果是纯粹为了 C 语言上机题,完全没必要大动干戈使用完整的 VS(至于 Dev C++?赶紧把这玩意儿丢进历史的垃圾堆吧),可以选择相对轻量的 Visual Studio Code。
其实我自己是在 2018 年大一的时候就已经开始在用 VSCode 了。不过最近有小朋友们问到了这个事情,就开一篇博客写一些吧(毕竟最近也没什么写的)。
话不多说,行くぞ!
先决条件
本文旨在讨论 Windows 环境下配置 VSCode 的开发环境,因此当然要先装好 VSCode 啦。
编译器的选择上,本文采用 TDM-GCC。选择它的原因是因为 64 位的 TDM-GCC 可以选择编译出 32 位还是 64 位的可执行文件,同时它的版本相对来说还算新的。在官网上下载时注意选择 64+32-bit 版本的。
如果追求更新的 GCC 版本,可以考虑使用 msys2。另外,极其不建议使用 MinGW-w64,它的 GCC 相对来说较旧(最后一个版本只到 8.1.0),而 8.1.0 又存在一个严重的 Bug。
编译器安装的时候,注意勾选添加 PATH 环境变量。完成之后,打开命令行界面,键入 gcc --version
然后回车。如果环境变量正确配置,将会看到如下图所示的输出。
安装好 VSCode 和编译器之后,我们开始进行配置。
配置 VSCode
VSCode 的开发配置是基于文件夹的,因此选择一个你喜欢的位置作为日后 C/C++ 单文件开发的项目文件夹,然后在 VSCode 中打开这个文件夹(如果在安装 VSCode 的时候注册了右键菜单,可以右击然后选择“通过 Code 打开”)。最新的 VSCode 会提示安全问题,选择“是,我信任此作者”。
然后我们新建一个 C 或者 C++ 源代码文件,并编写任意一段合法代码。习惯起见,下面我一律以 C++ 为例。
#include <bits/stdc++.h> using namespace std; int main() { cout << "Hello World!" << endl; return 0; }
编写完成之后,保存它。这个时候 VSCode 应该会提示你安装 C/C++ 语言开发插件,我们按照提示完成插件的安装。
插件安装完成之后,VSCode 会需要进行设置以配置 IntelliSense。最新版本的 VSCode 已经提供了图形化的界面,相比以前手动编写 JSON 会方便很多。点击“配置(UI)”。
在“编译器路径”一项中,正常情况下 VSCode 应该会检测到我们先前安装的 TDM-GCC,直接从下拉列表里选择即可。如果没有列出,那么就需要手动填写编译器安装目录下 bin
文件夹内编译器可执行文件的完整路径。关于选择 gcc
还是 g++
,这里建议选择 g++
。因为 G++ 编译 C 语言源代码文件比 GCC 编译 C++ 语言源代码文件会方便一些。
“编译器参数”部分,一般情况下我们需要的操作就是编译并输出可执行文件,因此填入下列内容即可,如后图所示。-std=c++17
可以不填,我这里只是比较喜欢用新一点的标准罢了。
-g -std=c++17 ${file} -o ${fileDirname}\\${fileBasenameNoExtension}.exe
“IntelliSense 模式”选择 windows-gcc-x64
。
“包含路径”填写下列内容。注意根据自己安装的编译器路径进行调整。
${workspaceFolder}/** C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/x86_64-w64-mingw32 C:/TDM-GCC-64/x86_64-w64-mingw32/include C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/backward
“C 标准”根据喜好选择 c11
或者 c17
。“C++ 标准”根据选择喜好选择 c++11
或者 c++17
,注意这里和上面的 -std=c++17
保持一致。GCC 10.3.0 对于 c++20
的支持似乎不太好,想选的话应该也行。
完成配置之后关掉设置选项卡,返回源代码。如果一切配置妥当,这时候应该所有红线都消失了,并且按下 Shift + Alt + F 能够正确格式化代码。
按下 F5,会弹出调试配置选择,这里我们选择“C++ (Windows)”。
然后会提示正在下载依赖,耐心等待。不过比较诡异的是下载的是 C# 的依赖,我也不知道为什么。
接下来生成调试配置文件,选择“默认配置”。
这个时候会打开 .launch.json
文件。将原有的 configuration
数组的内容删除,点击右下角的“添加配置...”,选择“C/C++:(gdb) 启动”。这个时候配置文件应该会变成下图所示的样子。
我们需要修改 program
和 miDebuggerPath
。miDebuggerPath
需要根据先前安装的编译器路径进行调整,使之指向 GDB 的可执行文件。修改后的文件内容如下。
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "(gdb) 启动", "type": "cppdbg", "request": "launch", "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "C:/TDM-GCC-64/bin/gdb.exe", "setupCommands": [ { "description": "为 gdb 启用整齐打印", "text": "-enable-pretty-printing", "ignoreFailures": true } ] } ] }
保存文件。点击“终端”→“配置默认生成任务...”,选择“C/C++:g++exe 生成活动文件”。
插件会根据我们之前填写的配置自动生成 tasks.json
文件,如图。
这里 args
数组的值有点问题需要修改,修改后的整个文件内容如下。
{ "version": "2.0.0", "tasks": [ { "type": "cppbuild", "label": "C/C++: g++.exe 生成活动文件", "command": "C:/TDM-GCC-64/bin/g++.exe", "args": [ "-fdiagnostics-color=always", "-g", "-std=c++17", "${file}", "-o", "${fileDirname}\\${fileBasenameNoExtension}.exe" ], "options": { "cwd": "C:/TDM-GCC-64/bin" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true }, "detail": "编译器: C:/TDM-GCC-64/bin/g++.exe" } ] }
对于初学者,可以酌情增加 -Wall
参数以帮助快速发现代码中的潜在问题。修改完毕之后保存。再次打开 launch.json
文件。向 configurations
数组里刚才配置好的项目加入 "preLaunchTask": "C/C++: g++.exe 生成活动文件"
,如下所示。这里的值对应了 tasks.json
里 tasks
数组配置好的项目中 label
的值。
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "(gdb) 启动", "type": "cppdbg", "request": "launch", "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "C:/TDM-GCC-64/bin/gdb.exe", "preLaunchTask": "C/C++: g++.exe 生成活动文件", "setupCommands": [ { "description": "为 gdb 启用整齐打印", "text": "-enable-pretty-printing", "ignoreFailures": true } ] } ] }
保存文件。返回到前面创建的 C/C++ 源代码文件。按下 F5,这时候会开始编译生成可执行文件并启动调试。在“调试控制台”选项卡中可以执行 GDB 命令,在“终端”选项卡中可以对程序进行输入输出。本文的例子中可以看到输出的 Hello World! 字样。
至此 VSCode 的配置即告完成。
使用 VSCode 进行断点调试
VSCode 的调试某种程度上来说师出 VS,比 Dev C++ 高到不知道哪里去了。下面来简单讲解一下如何进行断点调试。
#include <bits/stdc++.h> using namespace std; int main() { int a; cin >> a; for (int i = 0; i < 10; i++) { a++; } cout << a << endl; return 0; }
鼠标放在行号上,在行号的左边会出现一个小红点,点击它就成功在这一行打上了断点。我们在第 11 行 a++
下断点。
按下 F5。前面提到在“终端”选项卡中可以进行输入输出。这里我们输入 1 作为 a
的初值。
回车之后会发现程序暂停执行了,同时第 11 行被高亮标注起来,表明当前程序暂停到了第 11 行之前的位置。需要注意的是,高亮行的代码在断点的时候还尚未执行。因此这时候 a
的值仍旧是 1。
在左侧的“变量”窗格中,可以看到当前作用域内所有局部变量的值。如果有全局变量,也会在这里显示出来。Registers
中列出了所有寄存器的值。“监视”窗格中可以根据自己的需要,设定一些要关注的表达式的值。“调用堆栈”窗格中展示了当前断点处的调用堆栈,这个功能在分析多个函数嵌套调用时很有帮助。“断点”窗格中显示了当前文件中所有的断点,点击前面的复选框可以临时禁用或启用一个断点,在这里也可以批量禁用或者启用所有断点,还可以直接删除所有的断点。
如果想删除已经打过的断点,可以再次点击行号前的小红点使它消失。
按下 F5 或者 F9 可以继续执行,如果在后面的执行中遇到断点,VSCode 会再次暂停,直到没有断点或程序退出。
完
Windows 下 VSCode 的单文件 C/C++ 配置大致就是这样。这一套足够应付所有涉及到 OJ 的单文件编程了。初学编程,还是要打好基础,养成好习惯。
怪,为啥只有大于号没有转义
xmgg,断点调试的代码块处有误:< 被识别成了 < 。(闲的没事233,我不会说是我直接复制报错发现的(ó﹏ò。)ノ