一、用VSCode提升C/C++开发体验

青梧·2026-09-29 16:32

用 VSCode 日常写代码

上一篇文章里,你已经把源代码到二进制文件整条链路亲手走了一遍,代价是 —— 每改一次代码,都要回到终端重新敲一遍 gcc -g -Wall -fexec-charset=GBK hello.c -o hello;想看一个变量的变化,得反复敲 next 和 print。作为程序员,毫无疑问,偷懒是我们的美德 😎 ,那能不能简化这个过程,让我不要重复做这些操作呢?这也是程序员奉行的经典原则之一:DRY原则

说明 · DRY原则

DRY(Don't Repeat Yourself)​ 出自《程序员修炼之道》—— Every piece of knowledge must have a single, authoritative representation within a system. 注意宾语是 knowledge:它管的是"同一个决定只写一次", 不是"两段代码长得像"。反面的自嘲缩写是 WET(Write Everything Twice)。

所以我们现在也要把从源代码编译成二进制这一整套动作搬进 VSCode。而不是在终端一次次地重复敲命令。VSCode更像一间整理好的书房:工具还在原地(你的电脑上),只是都放到了顺手的位置(VSCode替你调用)。而你要做的第一件事,是搞清楚它到底替你把什么收了起来。

一个简笔人物把工具箱和书本搬进一间明亮整洁的小房间,屋里有桌子和椅子,墙上贴着几张空白便签

0、安装 VSCode

不管哪个系统,都从 https://code.visualstudio.com/ 下载。区别只在最后那几步:

Windows

页面上点 Download for Windows,下回来的是一个几十兆的安装包,一路 下一步 就能装完。

只有最后一页值得注意一下。安装向导的选择附加任务那一步里,有两个选项,其中一个你现在已经能够理解它是什么意思:

选项

勾上之后你会拥有

添加到 PATH

在任何终端里敲 code .,就能用 VSCode 打开当前文件夹

提示 · 融会贯通

你掌握了 PATH 的相关知识,以后再见到就能立刻理解。计算机的知识虽不算少,但重复用、常用的知识并没有那么多。

安装完成并将VSCode添加到PATH后,按下 Win + R,输入 powershell 回车,随便进一个文件夹敲:

在终端里执行

code .

如果 VSCode 打开了当前文件夹,说明它生效了,至于为什么生效,为什么系统能够找到code这个命令?你心里有数。

macOS

把下载到的 .zip 解开,将 Visual Studio Code.app 拖进应用程序文件夹,就装完了 —— 没有安装向导,也没有可以勾的选项。

所以那个 code . 命令要手动补上。在 VSCode 里按 Cmd + Shift + P 打开命令面板,输入并运行:

在命令面板里搜索并执行

Shell Command: Install 'code' command in PATH

运行完,终端里的 code . 就和 Windows 上一样可用了。

1、中文界面

VSCode 默认设置是英文。改成中文只需要装一个语言包。

点左侧活动栏最下面那个由四个小方块组成的图标(扩展,快捷键 Ctrl + Shift + X),在搜索框里输入 Chinese,找到 Chinese (Simplified) (简体中文) Language Pack,点 安装。装完右下角会弹出提示,点 Change Language and Restart,界面就是中文的了。

接着还差最关键的一个扩展。在同一个搜索框里输入 C/C++:

注意 · 认准作者是 Microsoft

商店里搜 C/C++ 会出来一堆名字很像的扩展,只有作者(Publisher)写着 Microsoft 的那个才是官方的。

装完 C/C++,旁边通常还会推荐 C/C++ Extension Pack —— 这是微软给 C/C++ 准备的全家桶,把常用的一整套(C/C++、CMake 支持、主题等)打包在一起。建议一次性装完,省得以后写大一点的作业时一个个补。

问答 · 为什么这两个扩展要分开装?

因为它们管的是两件不同的事:语言包改的是 VSCode 自己的界面文字,C/C++ 扩展负责看懂你的代码(语法高亮、补全、报错、以及后面要用的调试对接)。

所以VSCode本身的功能并不很多,你可以当做是一个更厉害的记事本,之所以它厉害,是因为它可以通过安装各种拓展,使其具备各种能力。

2、让 VSCode 记住那行编译命令:tasks.json

打开VSCode,点击左上角的 文件-->打开文件夹--> 选择你C语言代码存在的那个文件夹 文件夹打开之后,菜单里点 终端 → 配置默认生成任务。VSCode 会列出一串它能找到的编译器,选带 gcc 的那一项:

选择任务时你会看到

C/C++: gcc.exe 生成活动文件

点下去,.vscode/tasks.json 就自动生成好了,内容大概是:

.vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "cppbuild",
      "label": "C/C++: gcc.exe 生成活动文件",
      "command": "C:\\msys64\\ucrt64\\bin\\gcc.exe",
      "args": [
        "-fdiagnostics-color=always",
        "-g",
        "${file}",
        "-o",
        "${fileDirname}\\${fileBasenameNoExtension}.exe"
      ],
      "options": {
        "cwd": "${fileDirname}"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "detail": "编译器: gcc"
    }
  ]
}

这个tasks.json文件不是给你读的程序,而是一张写给 VSCode 看的「说明书」 —— 每次让它编译,它就照着这张说明书找到程序、拼好参数、执行命令。所以我们不需要背下这些东西,只要认出它回答的三个问题:让谁去干(command)、怎么干(args)、在哪个文件夹里干(cwd)。

先看 command:它就是编译器在你电脑上安装的位置(上面那个路径是我的电脑上的,你自己电脑上的路径取决于你安装在了哪里)

再看 args:它就是你在上一篇文章中终端编译源文件时敲过的那串东西。

一位简笔人物把一张空白小卡片插进墙上的卡片架,桌上放着笔记本电脑,旁边的小机器人捧着扳手待命

-g 还是那个 -g,-o 还是那个 -o,只不过文件名换成了三个占位符:

占位符

它在编译那一刻会变成什么

${file}

你当前打开的那个源文件,也就是 D:\code\c\hello.c

${fileDirname}

这个源文件所在的文件夹,也就是 D:\code\c

${fileBasenameNoExtension}

去掉后缀的文件名,也就是 hello

所以 -o "${fileDirname}\\${fileBasenameNoExtension}.exe" 展开之后,正好就是 -o "D:\code\c\hello.exe"。一套任务配置,能编译这个文件夹里所有 .c 文件 —— 换成 world.c,它自动编出 world.exe。这就是占位符的价值。

把展开前后摆在一起看,你会发现它比手敲的那条命令只多了一小段:

两种写法,同一个结果

gcc -g hello.c -o hello

VSCode按照tasks.json 展开后

gcc -fdiagnostics-color=always -g D:\code\c\hello.c -o D:\code\c\hello.exe

多出来的 -fdiagnostics-color=always 只管一件事:让报错带颜色 —— 错误标红、警告标黄,一眼就能看出轻重缓急。不加也照样能编译,只是整屏白字看着费劲。

提示 · 为什么参数要「竖着写」

args 里用 [ ] 把参数一项项排开,和横着写成一整行完全是同一件事:[ "-g", "${file}" ] 就等于 -g ${file}。 竖着写只有一个好处,但很实在 —— 以后要加参数只要加一行,不用在长长的一行里找该往哪儿插。

说明 · 占位符不只属于 VSCode

${file}、${fileDirname} 这类写法你在别的地方也会遇到。(或者说你已经遇到过了,细想一下,PATH是不是就是所谓的占位符?再去翻翻你的windows环境变量设置,然后再体会一下这种占位符用法的好处。)

Makefile 的变量、CMake 的 ${PROJECT_NAME}、Shell 的 $1 —— 本质都是同一招:先留个空,等真正执行时再填上。 现在认识它,以后在别的工具里见到就不会陌生。

再把剩下的几个键过一遍。了解即可

键

说人话

写错或删掉会怎样

version

这份文件的格式版本,固定写 "2.0.0"

不用改,也别删

tasks

任务列表。[ ] 里每写一段就是一个任务,同一个文件夹可以配好几个

没了它,VSCode 读不到任何任务

type

"cppbuild" 表示这个任务由 C/C++ 扩展提供

这正是非认准 Microsoft 那个扩展不可的原因:装成野生扩展,VSCode 根本不认识这个类型

label

这个任务的名字,launch.json 靠 preLaunchTask 按名字引用它

名字对不上,按 F5 就提示找不到任务

command

让谁去干活 —— gcc。系统按 PATH 那份清单把它找出来

和 2.6 里 code . 能生效是同一套机制;PATH 里没有它就报「不是内部或外部命令」

options.cwd

在哪个文件夹里执行这条命令,相当于先替你 cd 过去

影响相对路径怎么解析,指到源文件所在目录最省心

problemMatcher

把 gcc 打印的报错翻译成 VSCode 能标出来的条目

编译照样能过,但错误不能点着跳行、也没有红波浪线

group

"kind": "build" 说明这是构建任务,"isDefault": true 说明它是默认那个

少了 isDefault,Ctrl + Shift + B 会先弹出来问你「跑哪个」

detail

纯备注,只给人看

写错不影响运行

注意 · 最容易出错的一行:label

"label" 是这个任务的名字,后面 launch.json 会用 preLaunchTask 去引用它。 引用必须一字不差 —— 包括空格、大小写、C/C++ 后面的冒号,全都要对上。 手动改过 label 却忘了同步改 launch.json,是“按下 F5 没反应 / 提示找不到任务”这类问题的头号来源。

表里 group 那两个值合起来的效果就是 —— 按 Ctrl + Shift + B 直接跑它,不用再进任何菜单。

顺带说一句,这个文件是跟着文件夹走的:拷给同学、提交进 Git、换台电脑打开都能直接用。你手敲的那些命令,从这里开始不用再重敲第二遍。

最后提醒一件小事:JSON 这个格式本身,有三个「一碰就废」的地方。

新手改这个文件踩的坑,几乎都落在下面三条上。它们不是 VSCode 的规矩,而是 JSON 文件有格式要求:

事故

长什么样

为什么会废

逗号

每两项之间要有英文逗号,但最后一项后面不能有

多一个逗号,整个文件读不出来,任务列表直接空掉

中文标点

写成中文逗号、中文冒号或中文引号

JSON 只认英文半角标点,中文标点一律让它读不懂

反斜杠

D:\code\c 只写了一个 \

JSON 里 \ 是转义符号,必须写成 \\ —— 这就是 -o 那行为什么全是双反斜杠

现在回到 hello.c,按一下 Ctrl + Shift + B,下方的终端里会刷出编译信息,然后 D:\code\c 里多出 hello.exe。板块四里手敲的那条命令,现在只需要一个快捷键。

备注 · Mac 读者

Mac 上的流程完全一样(终端 → 配置默认生成任务),只是列表里显示的是 C/C++: clang 生成活动文件。 生成的 tasks.json 里改两个值就够了:"command" 填 clang,输出文件名末尾不带 .exe —— 写成 "${fileDirname}/${fileBasenameNoExtension}",注意用的是正斜杠。

如果终端提示 gcc 不是内部或外部命令

说明 VSCode 没能在 PATH 里找到 gcc。最直接的办法是把 command 换成完整路径:

"command": "C:\\mingw64\\bin\\gcc.exe",

注意反斜杠要写成两个(\\)。JSON 里单个 \ 是转义字符,C:\mingw64 这种写法会让 VSCode 读不懂这个文件,整个 tasks.json 直接失效。

换完之后记得把 "detail" 那一行也顺手改掉,它只是给人看的备注,写错了不影响运行。

3、用鼠标打断点:launch.json 与 F5

编译能用了,接着把调试搬进来。打开 hello.c,点左侧活动栏的 运行和调试 图标(或菜单 运行 → 添加配置...),在选择环境里选:

C++ (GDB/LLDB)

再在配置列表里选 C/C++: gcc.exe 生成和调试活动文件。.vscode/launch.json 就生成了:

.vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++: gcc.exe 生成和调试活动文件",
      "type": "cppdbg",
      "request": "launch",
      "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${fileDirname}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "miDebuggerPath": "C:\\mingw64\\bin\\gdb.exe",
      "setupCommands": [
        {
          "description": "为 gdb 启用整齐打印",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "C/C++: gcc.exe 生成活动文件"
    }
  ]
}

这个文件里有五个字段需要重点关注:

字段

它说的是什么

program

要调试的是可执行文件 hello.exe,不是源文件 hello.c。调试器只能操作真正能跑起来的东西 —— 这里写成 .c 是新手最常见的错

miDebuggerPath

用哪个调试器。就是跟着 MinGW 一起装进来的那个 gdb.exe

preLaunchTask

按 F5 之前,先跑哪个任务。它的值必须和 label 完全一致

externalConsole

是否另开一个黑框窗口。false 表示就在 VSCode 下方的终端里跑,看着更清楚

stopAtEntry

是否在 main 的第一行就停下来。false 表示不停,直接跑到你的断点

备注 · Mac 读者:这个文件里有三处不同

生成配置时同样选 C++ (GDB/LLDB),但填的值不一样:"MIMode" 用 "lldb"、"miDebuggerPath" 用 "/usr/bin/lldb"、"program" 去掉 .exe 后缀(写成 "${fileDirname}/${fileBasenameNoExtension}")。preLaunchTask 则要填 clang 任务的 label。

一条虚线小路上立着路标,一个简笔人物站在路标旁低头看手里的小本子

快捷键

干什么

F5

继续运行,直到下一个断点或程序结束

F10

单步跳过:执行下一行,不钻进函数里面

F11

单步进入:如果下一行是函数调用,就钻进去

Shift + F5

停止调试,强制结束程序

提示 · 这就是 gdb 的图形化版本

你不是换了一套工具,你用的是同一个 gdb:program 里的 hello.exe 是它启动的程序,miDebuggerPath 里的 gdb.exe 是它本体,点红点就是帮你敲了 break,按 F5 就是帮你敲了 run,按 F10 就是 next,看变量面板就是帮你敲了 print。 唯一的区别:命令它替你敲了,眼睛替你省了。

4、Code Runner:方便的代价

在扩展面板里还能找到另一个很受欢迎的扩展:Code Runner。装上之后,编辑器右上角会多出一个 ▶ 按钮,点一下就能跑,快捷键是 Ctrl + Alt + N。

听上去比 Ctrl + Shift + B 还省事。但它的默认行为里藏着两个坑 —— 把它的默认命令展开看:

Code Runner 对 .c 文件默认执行的命令

cd $dir && gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt

注意 · ① 没有 -g。 这条命令编译出来的程序里不含调试信息 —— 上篇文章说过,没有 -g,断点就是一句空话。所以用 Code Runner 跑出来的 hello.exe,F5 是调不动的。

② 不管编码。 它也不会替你加 -fexec-charset=GBK,程序里的中文照样可能变成乱码。

所以结论很清楚:Code Runner 适合“我就想快速试两行”,不适合正经写代码。 写作业、做课程设计,老老实实用 Ctrl + Shift + B 加 F5 —— 那套配置里既有 -g,又能打断点,还能一眼看到变量。

5、环境体检表

到这一步,整套环境已经齐了。回头看一眼你走过的路:

手工流程与 VSCode 的对应关系:手敲 gcc 命令对应 Ctrl+Shift+B,手敲 gdb 命令对应点断点按 F5,记住路径参数对应写进 .vscode 里两个配置文件

最后按下面这张表逐项验一遍。全部打勾,说明你的环境没有任何问题,可以放心开始写代码了:

#

验收项

怎么做

期望结果

1

编译器就位

终端里敲 gcc --version

打印出版本号

2

调试器就位

终端里敲 gdb --version

打印出版本号

3

VSCode 接进了终端

在 D:\code\c 里敲 code .

VSCode 打开这个文件夹

4

项目能识别

打开文件夹后,菜单里有 终端 → 配置默认生成任务

列表里出现 C/C++: gcc.exe 生成活动文件

5

一键编译

打开 hello.c,按 Ctrl + Shift + B

终端刷出编译信息,D:\code\c 里出现 hello.exe

6

程序跑得对

在 D:\code\c 里运行 .\hello

输出 "Hello, C!"

7

断点能用

在 printf("Hello, C!"); 行号左边点一下,按 F5

程序停在这一行

成功 · 到这里,你已经是一个能干活的人了

会安装编译器、会配置PATH让系统找得到安装的软件、会用终端命令计算机执行程序、通过配置文件让编辑器记住了你的命令从而实现一定程度的自动化、调试断点点一下就生效。 剩下的事只有一件 —— 开始写代码。


结语 · 环境配好之后,该往哪走

摘要 · 你真正拿到手的东西

不是“会装 VSCode”,而是知道每一步在发生什么。 别人按那个小三角按钮的时候只知道“跑起来了”;你知道那背后是 gcc 在做预处理、编译、汇编、链接,知道 -g 决定断点能不能生效,知道 PATH 是系统手里的那份通讯录,知道 VSCode 只是把你敲过的命令记进了两个 JSON 文件。 环境配置会随版本变化,这套原理不会。

接下来该往哪走?

  1. 不要急着换 IDE。 你以后一定会听到 VS / CLion / Vim 的名字,也可能被人劝“换一个更好用”。但是 —— 工具切换是几分钟的事,看懂编译、链接、调试这三件事才是值钱的。熟知原理才能以不变应万变,换任何工具都只是熟悉一下界面,况且VSCode大多数情况下已经足够好用。

  2. 先把命令行用熟。 -o 定输出名、-g 带调试信息、-Wall 开警告、-std= 定标准 —— 这四个参数够你用很久。更重要的是:服务器上不会有按钮给你点,命令行是你唯一的操作方式。

  3. 把调试器用熟。 断点、单步、查看变量,这三件套能解决你未来 80% 的“为什么结果不对”。学会先怀疑自己,再让程序停下来告诉你答案,而不是盯着代码发呆。

  4. 下一步学 Makefile,再进阶 CMake。 现在你只有一个 hello.c,手敲一条命令当然没问题。等当你需要编写三个 .c 文件互相调用的时候,你就该让机器替你记住“先编哪个、再链哪个”了 —— 这正是 Makefile 在干的事。

  5. 遇到报错,原样复制去搜。 不要用自己话转述,报错原文里的文件名、行号、错误码都是关键词。另外养成一个习惯:永远先看第一条 error,后面的错误常常是它的连锁反应。

  6. 动手才是真的学。 看十遍教程不如自己写一遍。可以从洛谷、力扣、牛客上找最简单的入门题开始,也可以把课本上的例题自己敲一遍再改几个数字试试。卡住的时候先别急着问,先自己调一次断点。

  7. 现在就可以学 Git。 不用等写大项目。哪怕只有一个 hello.c,也可以建一个仓库 —— 往后你会发现“能随时回到昨天那个能跑的版本”是一件多让人安心的事。

一张图看清接下来这几步的关系:

接下来这几步: ① 本文完成(环境全部跑通)→ ② 刷基础题(洛谷 / 力扣 / 牛客)→ ③ 读教材(《C Primer Plus》)→ ④ 学 Git(把代码管起来)→ ⑤ 学 Makefile(多文件自动构建)→ ⑥ 进阶 CMake(工程级项目)

顺序不必严格照搬 —— 先学 Git 再刷题也完全可以。但有一点值得记住:每一步都踩在已经跑通的环境上往前半步,而不是推倒重来。

祝你的第一个程序顺利跑通。 从今天起,我希望读者能够记住从小开始就耳熟能详的那句话:“基础不牢,地动山摇”。