Ubuntu 20.04下C/C++开发环境搭建:VS Code与GCC/GDB工具链配置指南
发布时间:2026/10/14 23:19:23 锦皓数字建站

1. 为什么在 Ubuntu 20.04 上折腾 C/C 开发环境值得认真对待1.1 从一次真实的踩坑经历说起先说个我自己的经历。几年前我刚把主力开发机换成 Ubuntu 20.04 的时候觉得装个编辑器写 C 代码能有多难结果光是让#include stdio.h下面不出现红色波浪线就折腾了整整一个下午。后来才发现问题根本不在代码本身而在于编辑器找不到系统头文件路径编译器版本和配置对不上调试器也没接上。这件事让我意识到一个很朴素的道理在 Linux 上写 C/C编辑器本身只是冰山一角真正决定开发体验的是它背后那套工具链有没有被正确串起来。编译器、调试器、代码分析引擎、构建系统这几样东西缺一个你的开发环境就是残废的。这篇内容就是把我这些年反复在 Ubuntu 20.04 上配置 C/C 开发环境的经验整理出来。不管你是刚接触 Linux 的学生还是从 Windows 转过来的老程序员或者是想给团队统一开发环境的工程师这套流程都能直接抄作业。我会把每一步为什么这么做讲清楚而不是甩给你一堆命令让你自己猜。1.2 先搞清楚我们要装的是什么很多人一上来就说我要装个写 C 代码的软件这个说法其实很模糊。我们真正要搭建的是一套完整的开发环境它至少包含四个层次编辑器层负责写代码、高亮语法、智能补全这里我们选 VS Code。编译工具链层负责把源码变成可执行文件核心是 GCC/G 和 make。调试层负责断点、单步、查看变量核心是 GDB。智能感知层负责代码跳转、错误提示、自动补全核心是语言服务器和配置文件。这四层里VS Code 只是最上面那层皮。真正让新手抓狂的往往是下面三层没配好导致编辑器看起来能用实际处处报错。所以接下来的内容我会按照从底层到上层的顺序来讲先把工具链装扎实再回头配置编辑器。提示Ubuntu 20.04 自带的软件源里GCC 默认是 9.x 版本这个版本对 C17 支持已经相当完整日常开发完全够用。如果你有特殊需求要装更新的版本后面我会单独讲怎么处理多版本共存。1.3 这套环境适合谁能解决什么问题这套配置方案特别适合以下几类人一是刚学 C/C 语言、需要在 Linux 环境下做课程作业的同学二是做嵌入式、系统编程、算法竞赛需要频繁编译调试的开发者三是习惯了图形化 IDE但又想体验 Linux 原生开发流程的转岗人员。它能解决的问题也很明确让你在 Ubuntu 上拥有接近甚至超过 Windows 下 Visual Studio 的开发体验包括智能补全、函数跳转、断点调试、多文件项目管理。而且整套方案完全免费不依赖任何商业授权。2. 装 VS Code 之前先把编译工具链打牢2.1 更新软件源并安装基础编译工具很多人拿到新系统第一件事就是去官网下 VS Code 的 deb 包这个顺序其实是反的。正确的做法是先确保系统自带的编译工具链是完整的否则后面编辑器配置好了一编译还是报错。打开终端先更新一下软件包索引sudo apt update sudo apt upgrade -y这一步别嫌慢Ubuntu 20.04 刚装好的时候软件源索引可能是旧的直接装东西容易遇到依赖冲突。更新完之后安装核心的编译工具sudo apt install build-essential -y这个build-essential是个元包它会一次性把 GCC、G、make、libc 开发头文件这些全都装上。我见过太多人只装了gcc却忘了g结果写 C 的时候一脸懵。装完之后验证一下gcc --version g --version make --version三条命令都能正常输出版本号说明工具链没问题。如果g提示找不到命令那就是没装全重新跑一遍上面的安装命令。2.2 安装调试器 GDB 和代码格式化工具编译工具装完接下来是调试器。VS Code 的调试功能本质上是调用 GDB 来工作的所以 GDB 必须单独装sudo apt install gdb -y装完之后可以用gdb --version确认。这里有个细节要注意Ubuntu 20.04 默认的 GDB 版本是 9.x配合 GCC 9 使用没有问题。如果你后面升级了 GCC 到更高版本GDB 最好也同步升级否则调试时可能出现符号表读取异常。另外我强烈建议顺手装上代码格式化工具写 C/C 代码不格式化时间长了代码风格会乱得没法看sudo apt install clang-format -yclang-format支持多种代码风格预设也可以自定义规则。后面在 VS Code 里配置保存时自动格式化能省下大量手动调整缩进的时间。2.3 验证工具链是否真的能跑通装完不代表能用我习惯用一个最小例子验证整条链路。新建一个目录写一个最简单的 C 程序mkdir -p ~/test_env cd ~/test_env创建hello.c#include stdio.h int main(void) { printf(环境验证通过\n); return 0; }然后编译运行gcc hello.c -o hello ./hello看到输出环境验证通过说明编译链路是通的。接着验证调试链路用 GDB 加载这个程序gdb ./hello进入 GDB 后输入run如果程序正常执行并退出说明调试器也能用。输入quit退出。这一步看起来简单但它能帮你提前排除掉后面配置编辑器时可能遇到的一大半问题。注意如果你在 GDB 里看到 No debugging symbols found 这类提示那是因为编译时没加-g参数。调试用的程序一定要用gcc -g hello.c -o hello这样编译否则断点根本打不上。3. 安装 VS Code 并配置中文与基础插件3.1 选择适合 Ubuntu 的安装方式VS Code 在 Ubuntu 上有好几种安装方式我逐个说一下优劣。第一种是从官网下载.deb包手动安装好处是版本可控坏处是每次更新都要手动下载。第二种是通过 Snap 安装命令简单但 Snap 版本的启动速度在某些机器上会偏慢而且文件系统访问权限有时会有奇怪的问题。第三种是添加微软的软件源用 apt 管理这样能自动更新也是我个人最推荐的方式。添加软件源并安装的命令如下sudo apt install wget gpg apt-transport-https -y wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor packages.microsoft.gpg sudo install -o root -g root -m 644 packages.microsoft.gpg /etc/apt/trusted.gpg.d/ sudo sh -c echo deb [archamd64 signed-by/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main /etc/apt/sources.list.d/vscode.list sudo apt update sudo apt install code -y这一串命令做完VS Code 就装好了而且以后sudo apt upgrade的时候会自动带上它。装完在终端输入code --version能看到版本号就说明成功了。3.2 首次启动后的必要设置第一次启动 VS Code建议先做几件事。第一是安装中文语言包在扩展面板搜索 Chinese 找到官方简体中文包安装然后重启生效。第二是熟悉一下界面布局左侧是活动栏中间是编辑区底部是终端和问题面板右侧是缩略图。第三件事很多人会忽略就是配置终端的默认 Shell。Ubuntu 20.04 默认是 bash如果你装了 zsh 或者其他 Shell可以在设置里搜索terminal.integrated.defaultProfile.linux来切换。这个设置影响的是 VS Code 内置终端的行为配好了能省不少切换窗口的麻烦。3.3 必装的 C/C 相关插件清单VS Code 本身只是个编辑器写 C/C 的能力全靠插件。下面这几个是我认为必装的插件名称作用是否必装C/C提供智能感知、调试、代码导航必装C/C Extension Pack打包了常用 C 扩展推荐CMake Tools如果用 CMake 构建项目按需Code Runner一键运行单文件程序推荐clang-format代码格式化集成推荐其中 C/C 插件是核心它内置了 IntelliSense 引擎负责代码补全和错误提示。安装完之后打开一个.c或.cpp文件右下角会提示你选择配置先别急着点等我们把配置文件理清楚再说。提示插件装多了会拖慢启动速度尤其是那些功能重叠的。我建议只装真正用得上的不要看到推荐就全装。C/C 这一个插件其实已经覆盖了 90% 的日常需求。4. 核心配置文件逐个拆解4.1 理解三个配置文件的分工VS Code 的 C/C 开发环境核心是三个配置文件它们放在项目根目录的.vscode文件夹里。很多人配不明白就是因为没搞清楚这三个文件各自管什么c_cpp_properties.json管智能感知告诉编辑器头文件在哪、用哪个编译器。tasks.json管构建定义怎么编译你的代码。launch.json管调试定义怎么启动调试器、传什么参数。这三个文件是相互独立的但又有联系。比如launch.json里调试的程序路径必须和tasks.json里编译输出的路径对得上否则调试时会提示找不到可执行文件。下面我逐个拆解。4.2 c_cpp_properties.json让红色波浪线消失这个文件解决的是编辑器找不到头文件的问题。默认情况下VS Code 不知道你的系统头文件在/usr/include也不知道你用的是 GCC 还是 Clang所以会在#include下面画红线。在项目根目录创建.vscode/c_cpp_properties.json内容如下{ configurations: [ { name: Linux, includePath: [ ${workspaceFolder}/**, /usr/include, /usr/local/include ], defines: [], compilerPath: /usr/bin/gcc, cStandard: c17, cppStandard: c17, intelliSenseMode: linux-gcc-x64 } ], version: 4 }这里几个关键字段解释一下。includePath是头文件搜索路径${workspaceFolder}/**表示递归包含项目内所有目录后面两个是系统头文件路径。compilerPath指向 GCC 的绝对路径这个很重要VS Code 会通过它自动推断出系统头文件的位置。cStandard和cppStandard指定语言标准C 用 c17C 用 c17这两个标准在 Ubuntu 20.04 的 GCC 9 上支持都很好。配好之后如果还有红线可以按CtrlShiftP打开命令面板输入 C/C: Edit configurations (UI) 检查一下或者直接重启 VS Code 让配置生效。4.3 tasks.json定义编译任务tasks.json管的是怎么把源码变成可执行文件。VS Code 本身不会编译代码它是通过调用外部命令来完成的这个文件就是告诉它调用什么命令、带什么参数。一个支持多文件编译的tasks.json示例如下{ version: 2.0.0, tasks: [ { label: build, type: shell, command: /usr/bin/gcc, args: [ -g, -Wall, -stdc17, ${file}, -o, ${fileDirname}/${fileBasenameNoExtension} ], group: { kind: build, isDefault: true }, problemMatcher: [$gcc] } ] }这里的参数值得细说。-g生成调试信息不加这个断点打不上。-Wall开启所有常见警告写 C 代码不开警告等于闭着眼睛开车。-stdc17指定语言标准。${file}是当前打开的文件${fileDirname}是文件所在目录${fileBasenameNoExtension}是不带扩展名的文件名。这样配置后按CtrlShiftB就能编译当前文件生成的可执行文件和源文件在同一目录。如果你写的是 C把command改成/usr/bin/g-stdc17改成-stdc17即可。多文件项目的话把${file}换成${workspaceFolder}/*.c或者用 Makefile 来管理后面我会单独讲。4.4 launch.json让断点真正生效launch.json管的是调试。没有这个文件你按 F5 是没法启动调试的。一个标准的 C 调试配置如下{ version: 0.2.0, configurations: [ { name: Debug C, type: cppdbg, request: launch, program: ${fileDirname}/${fileBasenameNoExtension}, args: [], stopAtEntry: false, cwd: ${fileDirname}, environment: [], externalConsole: false, MIMode: gdb, setupCommands: [ { description: 为 gdb 启用整齐打印, text: -enable-pretty-printing, ignoreFailures: true } ], preLaunchTask: build } ] }关键字段里program指定要调试的可执行文件路径必须和tasks.json里输出的路径一致。preLaunchTask指定调试前先执行哪个任务这里填build对应tasks.json里的 label这样按 F5 的时候会自动先编译再调试非常方便。MIMode指定用 GDB。externalConsole设为 false 表示用 VS Code 内置终端设为 true 会弹出一个独立终端窗口看个人习惯。注意preLaunchTask的值必须和tasks.json里label的值完全一致大小写敏感。我见过有人写成 Build 结果一直提示找不到任务排查半天。5. 从单文件到多文件项目的完整实操5.1 单文件程序的编译与调试全流程先用一个单文件例子把整个流程走通。新建main.c#include stdio.h int add(int a, int b) { return a b; } int main(void) { int result add(3, 5); printf(结果是: %d\n, result); return 0; }按CtrlShiftB编译如果没有报错会在同目录生成main可执行文件。然后在int result add(3, 5);这一行左侧点一下打上红色断点。按 F5 启动调试程序会停在断点处左侧变量面板能看到a和b的值把鼠标悬停在变量上也能看到当前值。按 F10 单步跳过F11 单步进入F5 继续运行。这一套流程走通说明你的环境已经完全可用了。如果断点没停八成是编译时没加-g或者program路径配错了。5.2 多文件项目的组织方式实际项目很少只有一个文件。假设你有三个文件main.c、math_utils.c、math_utils.h。目录结构如下project/ ├── .vscode/ │ ├── c_cpp_properties.json │ ├── tasks.json │ └── launch.json ├── main.c ├── math_utils.c └── math_utils.hmath_utils.h里声明函数#ifndef MATH_UTILS_H #define MATH_UTILS_H int add(int a, int b); int multiply(int a, int b); #endifmath_utils.c里实现#include math_utils.h int add(int a, int b) { return a b; } int multiply(int a, int b) { return a * b; }main.c里调用#include stdio.h #include math_utils.h int main(void) { printf(3 5 %d\n, add(3, 5)); printf(3 * 5 %d\n, multiply(3, 5)); return 0; }这时候tasks.json里的编译命令要改不能只编译${file}了得把所有.c文件都编进去args: [ -g, -Wall, -stdc17, ${workspaceFolder}/*.c, -o, ${workspaceFolder}/main ]launch.json里的program也要相应改成${workspaceFolder}/main。这样按 F5 就能编译整个项目并调试。5.3 用 Makefile 管理更复杂的项目当文件多到十几个的时候每次都全量编译会很慢。这时候就该上 Makefile 了。一个基础的 Makefile 长这样CC gcc CFLAGS -g -Wall -stdc17 TARGET main SRCS $(wildcard *.c) OBJS $(SRCS:.c.o) $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) %.o: %.c $(CC) $(CFLAGS) -c $ -o $ clean: rm -f $(OBJS) $(TARGET)这个 Makefile 会自动扫描当前目录所有.c文件分别编译成.o目标文件最后链接成可执行文件。改动了哪个文件只会重新编译那一个效率高很多。配合 Makefiletasks.json改成调用 make{ label: build, type: shell, command: make, args: [], group: { kind: build, isDefault: true }, problemMatcher: [$gcc] }launch.json里的preLaunchTask保持build不变program指向 Makefile 生成的可执行文件路径。这样整个流程就串起来了。6. 常见问题排查与避坑经验6.1 智能感知失效的几种典型情况智能感知失效是最常见的问题表现就是代码补全不出来、函数跳转不了、头文件下面全是红线。根据我的经验原因主要有这么几类第一种是compilerPath配错了。如果你系统里装了多个版本的 GCC路径可能不是/usr/bin/gcc。用which gcc确认一下实际路径。第二种是includePath没包含项目目录尤其是头文件放在子目录里的时候必须加上${workspaceFolder}/**。第三种是 IntelliSense 引擎卡死了这时候按CtrlShiftP输入 C/C: Reset IntelliSense Database 重置一下数据库通常能解决。还有一种比较隐蔽的情况项目路径里有中文或空格。VS Code 对这类路径的处理偶尔会出问题建议项目路径全用英文不要有空格。6.2 调试时断点不生效的排查思路断点不生效按下面的顺序排查现象可能原因解决方法断点变空心圆编译时没加 -g在编译参数里加 -g提示找不到程序program 路径错误检查 launch.json 的 program 字段断点被忽略代码被优化了编译时加 -O0 关闭优化调试器启动失败GDB 未安装或版本不匹配重新安装 gdb 并检查版本其中断点变空心圆是最常见的本质就是可执行文件里没有调试符号。很多人编译的时候图省事不加-g调试的时候又纳闷为什么断点不停其实就是这个原因。6.3 编译报错的快速定位技巧GCC 的报错信息有时候很长新手容易看晕。我的经验是永远从第一条错误开始看因为后面的错误往往是第一条引发的连锁反应。比如头文件没找到后面会跟着一堆未定义的错误其实只要解决头文件路径问题后面全都会消失。另外-Wall打开的警告要认真看。C 语言里很多警告其实是潜在 bug比如使用了未初始化的变量、隐式声明函数这些在运行时可能表现为随机崩溃非常难查。养成看警告的习惯能帮你省下大量调试时间。提示如果报错信息太长可以在终端里用gcc ... 21 | less来分页查看或者把输出重定向到文件里慢慢看。VS Code 的问题面板也会把错误和警告分类列出点一下就能跳到对应代码行。6.4 几个我踩过的坑第一个坑是权限问题。有次我把项目放在/opt目录下编译时一直提示权限不足折腾半天才发现是目录权限的问题。后来我养成习惯项目一律放在用户主目录下省心。第二个坑是编码问题。从 Windows 拷过来的 C 文件可能是 GBK 编码在 Ubuntu 下打开中文注释全是乱码编译还可能报错。解决办法是在 VS Code 右下角把文件编码改成 UTF-8然后另存。第三个坑是多个 GCC 版本冲突。有次我手动装了 GCC 11结果gcc命令指向的还是 9但g指向了 11导致 C 和 C 混编时出现奇怪的链接错误。后来用update-alternatives统一管理版本才解决。如果你也遇到类似情况可以用update-alternatives --config gcc来切换默认版本。7. 让开发体验再上一个台阶的进阶配置7.1 保存时自动格式化的配置方法代码格式化这件事手动做永远坚持不下来最好的办法是保存时自动执行。在 VS Code 设置里搜索format on save勾选 Editor: Format On Save。然后在项目根目录创建.clang-format文件定义你的代码风格BasedOnStyle: Google IndentWidth: 4 ColumnLimit: 100 AllowShortFunctionsOnASingleLine: None这个配置基于 Google 风格但把缩进改成 4 空格行宽限制改成 100 字符不允许短函数写在一行。配好之后每次保存文件clang-format会自动帮你整理格式团队协作时再也不用为缩进吵架了。7.2 用 Code Runner 一键运行单文件对于写算法题或者做小测试的场景每次都按 F5 调试有点重。这时候 Code Runner 插件就派上用场了。装完之后打开一个 C 文件右上角会出现一个三角形播放按钮点一下就能直接编译运行输出显示在底部的输出面板里。不过 Code Runner 默认的编译参数比较简单建议在设置里自定义一下。搜索code-runner.executorMap找到 C 和 C 的配置项改成c: cd $dir gcc -g -Wall -stdc17 $fileName -o $fileNameWithoutExt $dir$fileNameWithoutExt, cpp: cd $dir g -g -Wall -stdc17 $fileName -o $fileNameWithoutExt $dir$fileNameWithoutExt这样一键运行的时候也会带上调试信息和警告和正式编译保持一致。7.3 终端与快捷键的效率优化VS Code 内置终端默认用 bash如果你经常需要同时开多个终端可以用CtrlShift5快速分屏。另外把常用的编译命令做成别名能省不少事。在~/.bashrc里加上alias mkmake alias mkcmake clean make alias run./main然后source ~/.bashrc生效。这样在终端里敲mkc就能清理并重新编译敲run就能运行程序。快捷键方面我常用的几个是CtrlP快速打开文件CtrlShiftF全局搜索CtrlShiftB编译F5调试F9打/取消断点F10单步跳过F11单步进入。这几个键位用熟了开发效率能提升一大截。7.4 版本控制与协作的衔接项目做大了迟早要用版本控制。VS Code 内置了 Git 支持左侧活动栏第三个图标就是源代码管理。初始化仓库、提交、推送这些操作都能在界面里完成不用记命令。不过有个细节要注意.vscode文件夹要不要提交到仓库我的建议是提交因为里面的配置文件是团队共享的统一配置能避免在我机器上能跑的经典问题。但如果你在配置里写了个人绝对路径那就要小心了最好用${workspaceFolder}这类变量代替硬编码路径。另外编译生成的.o文件和可执行文件不应该提交在项目根目录创建.gitignore*.o main *.out这样仓库里只保留源码和配置干净清爽。8. 关于这套环境的一些个人体会配置开发环境这件事看起来是体力活其实很考验对工具链的理解。我见过太多人把 VS Code 当成一个高级记事本来用装完插件就以为万事大吉结果遇到问题完全不知道从哪下手。真正高效的开发者往往是对底层工具链有清晰认知的人他们知道编辑器只是壳编译器、调试器、构建系统才是核心。这套在 Ubuntu 20.04 上的配置方案我前后在好几台机器上重复过每次都会根据实际情况微调。比如有的机器上 GCC 版本比较新c_cpp_properties.json里的intelliSenseMode就要相应调整有的项目用 CMake 构建那tasks.json就要换成调用 CMake 的命令。但万变不离其宗只要理解了三个配置文件的分工剩下的就是按需修改。最后分享一个小技巧把你调试好的.vscode文件夹保存一份模板下次开新项目直接复制过去改改路径就能用能省下大量重复配置的时间。这个习惯我坚持了好几年每次新建项目至少省半小时。环境配置这种事一次投入长期受益值得花时间把它做扎实。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。