☰
麒麟系统从零搭建C语言环境:gcc安装、编译原理与Hello world实战
2026/10/15 7:03:39 网站建设 项目流程

不少开发者的工作环境正在从原来的 Windows 或者某个发行版 Linux,慢慢切到麒麟系的国产操作系统上。业务跑在麒麟服务器上,桌面办公也是麒麟,那么作为开发者的第一步,往往就是在这个新环境里把最基础的 C 语言程序跑起来——没错,就是那句 Hello world。这件事听起来简单,但真正落地时你会遇到工具链缺没缺、编辑器怎么用、编译器怎么装、权限够不够这些问题。我写这篇文章,就是想把从空白麒麟系统到成功输出 Hello world 的完整路径拆开讲一遍,包含每一步背后的原理、我踩过的坑,以及从这句 Hello world 往后延伸的工程化思路,给准备在麒麟上开始写 C 语言的朋友一份可以直接照着做的参考。

1. 先把思路捋清楚:为什么是麒麟,为什么从 Hello world 开始

1.1 麒麟系统与开发环境的基本盘

麒麟系统本质上是 Linux 内核发行版,桌面环境和软件包管理方式都遵循 Linux 体系。也就是说,只要你会用 Ubuntu 或者 Debian,切到麒麟上基本不会有很强的陌生感。终端、文件权限、目录结构、编译工具,这些核心概念全都通用。

但有一个常见误区,就是以为系统装在桌面版上就自带全套开发工具。事实上不少麒麟版本默认只装办公软件、浏览器这些基础应用,gcc 并不在预装列表里。服务器版更明显,很多是精简安装,连图形界面都没有,更别提编译器了。很多人照着网上教程敲了一行 gcc 却提示找不到命令,根源就在这里,不是系统有问题,是它没预装而已。

在开发这件事上,系统名其实不重要,重要的是 Linux 生态。你会了 gcc,在麒麟下写 C 和在其他 Linux 发行版下写 C,没有任何本质区别。这一点想明白了,后续学习就不会被“国产系统”这个词吓住。

1.2 Hello world 不是“玩具”,而是开发链路的最小闭环

为什么每一门语言的入门都是从 Hello world 开始?因为它能验证整条开发链路是否通畅。写一个 C 程序,表面上只是输出一行字,背后的链路其实是这样的:

  • 编辑器:负责把源码写成纯文本文件。
  • 编译器:负责把源码翻译成机器能识别的指令。
  • 链接器:把编译产物和系统库合并成可执行文件。
  • 系统加载器:在终端里运行这个可执行文件,完成最后的输出。

这四个环节缺一不可。编辑器没装,你写不了代码;编译器没装,源码就是一堆文本;链接失败,可执行文件生成不了;运行不了,那就是权限或者路径问题。Hello world 这个例子虽然简单,但它像一条最小闭环的流水线,任何一个环节出问题都会卡住,所以它天然就是一个环境体检工具。你在麒麟上把 Hello world 跑通了,说明你的开发环境具备了跑 C 程序的基础条件,接下来写任何程序都只是在这个闭环上做加法。

1.3 这个环境解决了什么问题、谁需要看

这篇文章针对三类人最有用。

第一类是刚换到麒麟环境的开发工程师,平时要写 C 或者 C++,需要快速搭好开发环境。第二类是高校里实验课用麒麟机房的学生,教材里用的是通用的 Linux 命令,但机房系统换了,跟着教程走会卡在环境差异上。第三类是负责适配验证的测试和运维,不一定要写复杂业务代码,但要能确认系统上能不能编译、能不能跑可执行文件。

如果你是资深开发,前面准备章节可以快速扫过,重点看后面编译原理的实战演示和问题排查清单,那些内容在不同 Linux 环境下都是通用的。

2. 动手前的准备:检查环境、安装 gcc、选编辑器

2.1 先查工具链在不在:一句命令看清家底

打开终端的方式,一般桌面环境下按 Ctrl+Alt+T 就能调出。麒麟桌面系统不管是哪个系列,快捷键基本都沿用了 Linux 的默认习惯,所以这对新手来说是第一个要记住的组合键。

终端打开后,第一件事不是急着写代码,而是先看看系统里有没有 gcc。执行这条命令:

gcc --version

如果你看到类似gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0的输出,说明编译器已经装好了,可以直接跳到下一节。如果提示bash: gcc: 未找到命令,那就要走安装流程。

再配合执行一条:

which gcc

这个命令会显示 gcc 的绝对路径,比如/usr/bin/gcc。如果两个命令都没结果,说明它确实没装。

这里我还建议顺手看下系统架构:

uname -m

输出如果是x86_64,说明是普通的 AMD64 架构;如果是aarch64,说明是 ARM 架构。为什么要看这个?因为你以后可能会从网上下载编译好的库或者二进制工具,架构不对就运行不了。麒麟系统在不同硬件平台上的部署很常见,搞清楚自己的架构能少很多麻烦。

2.2 没有 gcc 怎么装:包管理的两种常见姿势

麒麟系统多数版本基于 Debian 体系,软件包管理走的是 apt 路线。安装 gcc 之前,先更新一下软件仓库索引:

sudo apt update

这里有一个新手经常懵的地方:输入sudo回车之后,终端不会显示密码输入过程,你输进去的密码一个字符都不显示,这是正常的,不是卡死了。输完之后回车,系统会校验权限。

接着安装 gcc 和基础构建工具:

sudo apt install -y gcc build-essential

build-essential这个包很关键,它不只是一个编译器,还会把 C 语言开发常用的头文件、链接工具一起装进来,比如 make、ld、libc6-dev 这些。如果你只装 gcc,后面编译时大概率会遇到找不到stdio.h的问题,因为标准库头文件并不随 gcc 一起发布。

安装完成后再跑一次gcc --version,看到版本号输出就说明环境通了。

如果你执行sudo apt update时提示仓库源连接失败或者 404,那属于系统软件源配置问题,不在本文讨论范围内,但思路上是检查包管理器配置的仓库地址是否可用。一般情况下,麒麟预装的软件源在国内访问是正常的,先尝试完整执行一次 update,再 install。

2.3 编辑器选型:vim、nano 还是图形界面

编辑器是写代码的起点,但很多人会在“选哪个编辑器”上花太多时间。我的建议很直接:能用就行。只要能打开文件、输入内容、保存退出,对你当前阶段来说就够了。

三种常见选择对比如下:

编辑器特点适合人群
vim轻量、终端内运行、预装率高,但操作模式有学习成本愿意花半小时学基础操作的人
nano轻量、终端内运行、底部带快捷键提示,基本零门槛第一次接触 Linux 终端的新手
gedit图形界面、鼠标可操作、有菜单栏,符合日常习惯不习惯命令行编辑的人

如果你选择的系统里装了 gedit,鼠标操作是最接近 Windows 记事本体验的。但很多服务器版系统没图形界面,所以我还是建议至少熟悉一个终端编辑器。vim 是绕不开的选项,这里给出最小可用操作:

  1. 打开文件:vim hello.c
  2. 进入插入模式:按字母i,此时左下角会显示-- INSERT --
  3. 写入内容或者粘贴代码
  4. 回到命令模式:按Esc
  5. 保存并退出:输入:wq然后回车

新手常见的问题是保存时只敲了:w不回车、或者敲:q忘记保存,都会导致行为不符合预期。我的建议是记住:wq这一个组合命令就够了,保存加退出一步完成。

别在编辑器上死磕太久。有些初学者因为记不住 vim 快捷键就开始怀疑自己是不是不适合编程,其实完全没必要,编辑器只是个工具,你天天用,一周后自然就顺手了。

3. 写代码、编译、运行:Hello world 全程实录

3.1 创建文件:文件名与路径的技巧

先在终端里确认自己当前在哪个目录:

pwd

输出一般是/home/用户名,这就是你的家目录。我不建议直接把文件放在家目录的根上,更不建议放到桌面,因为以后文件会越来越多,乱成一团。建议创建专门的代码目录:

mkdir -p ~/code cd ~/code

文件名用hello.c,全部小写,扩展名必须是.c。不要用中文文件名,也不要带空格。原因很简单,中文文件名的编码在部分终端环境下会和系统区域设置冲突,空格会在后续命令行操作时需要转义,新手容易在这上面吃亏。

创建一个空文件可以用touch hello.c,也可以直接用编辑器新建。我更推荐直接用 vim 一步到位:vim hello.c,写入代码后:wq保存,这一步就同时完成了“创建文件”和“写入内容”两件事。

3.2 写入 Hello world 代码:逐行解析标准写法

在hello.c中输入以下内容:

#include <stdio.h> int main(void) { printf("Hello, Kylin!\n"); return 0; }

这是 C 语言入门最标准的写法。逐行解释一下:

  • #include <stdio.h>:这一行告诉编译器,我们需要使用标准输入输出库。stdio.h是标准头文件,里面声明了printf、scanf这些函数。编译器在后续阶段会把这个头文件的内容展开,塞进源码里。
  • int main(void):这是主函数的定义。程序启动后,系统会调用这个名字叫main的函数。void表示这个函数不接受任何参数。前面的int表示函数返回一个整数给系统。
  • { ... }:大括号圈定了函数体,所有实际执行的语句都在里面。
  • printf("Hello, Kylin!\n");:这是真正的输出语句。printf把双引号里的内容打印到终端,\n是换行符,表示打印完这句话后光标移到下一行。
  • return 0;:函数返回 0,代表程序正常结束。这是给系统看的信号,脚本可以通过这个返回值判断程序是否成功。

写代码时最容易出问题的不是逻辑,而是标点。中文输入法下打出的分号和引号,和英文的看起来很像,但编译器不认。新手写完代码后,快速检查三件事:引号是不是英文的、分号是不是英文的、大括号是不是成对的。这三样都对了,编译基本不会卡在语法错误上。

3.3 gcc 编译:从一条命令到可执行文件

写完代码,保存退出,回到终端,确认当前目录是~/code,然后执行编译:

gcc hello.c -o hello

这条命令的意思是把hello.c编译成可执行文件,-o后面的hello是输出文件名。如果你不加-o hello,gcc 会默认生成一个叫a.out的文件,这在演示时可以,但实际开发中没人希望自己编译的程序都叫同一个名字。

编译成功后,用ls查看目录:

ls

你会在目录下看到两个文件:hello.c和hello。再用file hello查看类型,如果输出是ELF 64-bit LSB executable之类的信息,说明这已经是一个标准的 Linux 可执行程序了。

运行它:

./hello

终端输出:

Hello, Kylin!

这里特别说一下为什么命令前面要加./。Linux 终端找命令的时候,会在PATH环境变量定义的目录列表里搜索,而当前目录默认不在这个列表里。你直接输入hello,shell 会去/usr/bin、/bin这些目录找,找不到就提示bash: hello: 命令未找到。./hello的意思是明确告诉 shell“在当前目录下找这个文件”,./就代表当前目录。

程序跑通之后,你可以试着改动一下源码里的字符串,比如把Kylin改成World,然后重新编译、重新运行。这个过程要形成肌肉记忆:改代码,就必须重新编译,不重新编译你运行到的还是旧版本。

3.4 进阶验证:加警告选项,看看程序到底经历了什么

基础编译通过只是起点。我建议你从第一天开始就养成一个习惯:编译时把警告选项带上:

gcc -Wall -Wextra hello.c -o hello

-Wall是启用常见警告,-Wextra是启用更多警告。编译器会在有问题的地方提醒你,比如变量声明了但没使用、函数缺少返回值、比较类型不匹配等等。这些警告不阻止生成可执行文件,但它们是编译器免费帮你做的代码评审,忽略它们等于浪费资源。

你可以做个实验:把源码里的printf语句末尾的换行符\n删掉,再用-Wall -Wextra编译,虽然程序还能跑,但输出的内容和行为会和预期不同。这类细节问题在后续工程化项目里会直接影响日志格式和调试效率,早点养成看警告的习惯,后面能省很多事。

4. 从 Hello world 往后看:编译过程与工程化准备

4.1 预处理、编译、汇编、链接:一条命令背后的事

gcc hello.c -o hello看着只是一条命令,实际背后做了四步工作。理解这四步能帮你解决很多“为什么编译失败”的问题。

阶段主要工作生成文件对应命令
预处理展开头文件、处理宏定义、删除注释hello.igcc -E hello.c -o hello.i
编译把 C 代码翻译成汇编语言hello.sgcc -S hello.i -o hello.s
汇编把汇编代码翻译成机器指令hello.ogcc -c hello.s -o hello.o
链接把目标文件和库合并成可执行文件hellogcc hello.o -o hello

我建议你亲自动手跑一遍分步编译,加深印象:

gcc -E hello.c -o hello.i gcc -S hello.c -o hello.s gcc -c hello.c -o hello.o gcc hello.o -o hello

打开hello.i你会看到一堆被展开的内容,那就是stdio.h里的一堆声明被塞进来了。打开hello.s你会看到汇编指令,printf那行对应的是一段复杂的函数调用序列。hello.o是二进制目标文件,还不能直接运行,因为printf这个函数的实现代码还没有被链进来。

链接这一步特别重要。printf的实际实现对程序员来说是个黑盒,它存在于系统的标准库中,通常是glibc。链接就是把你的代码和这些库代码合并,让最终的hello文件能够找到printf的机器码在哪里。这就是为什么只装 gcc 不够,还必须装标准库开发包的原因。

4.2 静态与动态:程序跑起来依赖什么

运行./hello时,程序并不是自给自足的。可以使用这个命令查看它的依赖:

ldd hello

输出会列出程序依赖的动态库,大概率会看到libc.so.6,这表示程序在运行时需要系统提供 C 标准库。这种链接方式叫动态链接,优点是可执行文件小,多个程序共享同一个库文件,节省内存和磁盘空间。

与之相对的是静态链接:

gcc -static hello.c -o hello_static

编译出来的文件体积会明显变大,因为所有用到的库代码都被直接塞进了可执行文件里,不再依赖外部库。ldd hello_static会提示它不是一个动态可执行文件。

动态链接和静态链接哪个好?日常开发用动态就够了。但有一种场景要用静态:你的程序要部署到一个目标机器上,而目标机器的系统库版本和开发机不一致,又不好随便更新,那静态编译一份带过去,跑起来最省心。理解这个区别,对以后部署和排查“为什么这台机器能跑那台机器不能跑”的问题很有帮助。

4.3 多文件与 Makefile:Hello world 的下一步

很多人在 Hello world 之后会困惑:真实项目不可能把所有代码塞进一个文件里,那多文件怎么办?

举个例子,假设把程序拆成两个文件。main.c负责主逻辑,print_hello.c负责具体打印,编译命令就是:

gcc main.c print_hello.c -o hello_v2

gcc 可以一次编译多个.c文件,然后自动链接成可执行文件。当一个工程文件数量变多、你还经常改其中某个文件时,每次都敲全部文件名就不再高效了。这时候可以用 Makefile 管理构建过程。

创建一个Makefile文件,内容如下:

hello_v2: main.c print_hello.c gcc main.c print_hello.c -o hello_v2

这句话表示:hello_v2这个目标的生成依赖main.c和print_hello.c这两个文件,下面缩进的行是生成规则。注意,这个缩进必须是 Tab 键,不能用空格代替,这是新手最容易踩的坑。

有了 Makefile 之后,你只需要在终端执行:

make

Make 工具会检查依赖文件的修改时间,如果只有main.c变了,它只需要重新编译main.c再链接,不用把所有文件全部重新编译一遍。这对于小项目感觉不到优势,工程大起来就知道有多重要了。Hello world 写完,我强烈建议你下一步就把 Makefile 用起来。

5. 我在实操中遇到的坑与排查清单

5.1 高频报错与解决办法

把常见问题整理成一张表,方便你遇到时直接查:

错误现象出现场景解决办法
bash: gcc: 未找到命令系统没装编译器安装 gcc 和 build-essential
hello.c:1:10: fatal error: stdio.h: 没有那个文件或目录缺标准库头文件安装 build-essential 或 libc6-dev
bash: ./hello: 权限不够文件没有可执行权限执行 chmod +x hello
bash: hello: 命令未找到直接输入可执行文件名用 ./hello 指定当前目录执行
中文乱码源码或输出含中文且区域设置不对先改用英文输出,再检查系统 locale
vim 里输入没反应可能按了 Ctrl+S 冻结终端按 Ctrl+Q 解除冻结
编译器报愚蠢错误:找不到 hello.c当前目录不对执行 pwd 和 ls 确认文件是否存在
编译时提示 Killed 进程被终止内存不够或 swap 不足检查 free -h,关闭大程序后重试

其中一个特别常见的情况是stdio.h找不到。新手很容易以为这是 gcc 的问题,其实是系统缺少标准库开发包。装完build-essential后这个报错会消失,因为里面带了所需的头文件。

5.2 两个容易忽略的“环境级”问题

第一个是 swap 空间不足导致的编译中断。你在小机器上编译大一点的项目时,可能会看到终端提示Killed,程序像被掐断一样消失了。这时跑dmesg | tail,大概率能看到系统因为内存不足启动了 OOM 清理机制。排查思路是看内存剩余量,适当增加 swap 或者分批次编译,别一上来就开十几路并行编译。

第二个是用户权限和目录归属的问题。有些开发者在系统上只有一个 root 账号可用,就直接用 root 写代码、编译。这虽然能跑通,但文件所有者都是 root,后续用普通用户访问时会出现权限报错,非常麻烦。我的建议是日常工作在普通用户下进行,只有安装软件才用 sudo。实践练习时把代码放在自己的家目录里,权限归属清晰,也贴合生产环境的安全习惯。

5.3 一个排查习惯:用 echo $? 看返回码

程序跑完,终端里就完事了吗?Linux 系统其实记录了上一个程序的退出状态。执行完./hello之后,再执行:

echo $?

如果输出0,说明程序正常退出。如果输出非零,说明程序异常结束。$?是 shell 里的特殊变量,保存着上一个命令的返回结果。这个方法特别适合写脚本时用,比如你写一个自动化测试脚本,Shell 脚本里判断编译和运行是否成功,靠的就是这个返回码。养成“不只看打印输出,还要看退出码”的习惯,排查问题时你会比别人多一个有效维度。

写在最后

在麒麟系统上写 C,环境本身并不会成为障碍,真正会拦路的大多是“小地方”:编译器有没有装、权限够不够、文件名对不对、当前目录是不是你以为的那个目录。我建议你把 Hello world 这一步当作一次“环境体检”,把 gcc、pwd、ls、./、ldd、echo $? 这几个命令用到滚瓜烂熟,顺手把-Wall -Wextra警告选项变成默认习惯。它们现在看起来简单,等到多文件项目、内网部署、目标机运行的时候,这些习惯能帮你省下大量排查时间。就从这个最简单的程序开始,把第一条链路跑通,后面的 C 语言学习会顺畅很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询