Menu

C 语言是什么?一切软件背后的编程语言

C 是一门诞生于 1972 年的小巧、快速的编译型语言,至今仍在驱动操作系统、数据库和几乎所有嵌入式设备。本文介绍它是什么、运行在哪里,以及为什么 2026 年仍值得学习。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

C 是一门编译型的通用编程语言,由 Dennis Ritchie 于 1972 年在贝尔实验室创造,用来编写 Unix 操作系统。它比同时代的几乎所有东西都活得更久,原因很简单:C 只比机器高出薄薄的一层。它让你直接访问内存和 CPU 的真实能力,同时读起来仍然像是人写的代码。

半个世纪后,它依然是用来构建其他语言的语言。

一个完整的 C 程序

用六行代码就能看出整门语言的样子。点击“运行”。

#include <stdio.h> 引入标准输入输出的声明,这样 printf 才能被识别。main 是每个 C 程序开始执行的地方。printf 输出文本,\n 是换行符,return 0 告诉操作系统程序已成功结束。这就是一个完整的、可以编译的程序:不需要用类包起来,底下也没有任何框架。

C 语言有什么不同

大多数现代语言都会把机器对你隐藏起来。C 刻意不这样做。

  • 它被编译成本机代码。 C 程序会变成某种 CPU 的机器指令并直接运行,中间没有解释器,也没有虚拟机。
  • 内存由你自己管理。 没有垃圾回收器。你申请内存,用完再归还。这会多一些工作,但这也是 C 程序占用内存如此之少、运行时间如此可预测的原因。
  • 它很小。 C 大约只有 32 个关键字。你可以把整门语言装在脑子里,而 C++、Java 或 Python 都做不到。
  • 几乎没有运行时。 C 程序可以运行在只有几 KB 内存、完全没有操作系统的微控制器上。

代价是用坦诚换掉了安全。C 会允许你读取数组末尾之后的内容,或使用已经释放的内存,而不会阻止你。这些错误都有名字:段错误、内存泄漏、未定义行为。学习 C 很大程度上就是学会避开它们。

C 语言运行在哪里

C 不是一件历史古董。此刻它就在你阅读本文的设备上运行着,而且不止一处。

  • 操作系统。 Linux 内核大约有 3000 万行 C 代码。Windows 和苹果内核的大部分也是用 C 写的。
  • 嵌入式系统。 汽车、温控器、医疗设备、路由器和洗衣机里的微控制器,绝大多数都用 C 编程。当整颗芯片只有 32 KB 内存时,C 往往是唯一现实的选择。
  • 数据库。 SQLite、PostgreSQL、MySQL 和 Redis 都是 C 程序。
  • 语言运行时。 Python 的官方解释器 CPython 是用 C 写的。Ruby 的 MRI、PHP 的 Zend 引擎和 Lua 的核心也是。当 Python “太慢”时,解决办法通常是写一个 C 扩展。
  • 工具和库。 Git、curl、FFmpeg、OpenSSL、zlib,还有 SQLite:计算世界的基础设施层就是 C。

这也是 C 的应用二进制接口(ABI)如此重要的原因:几乎所有语言都能调用 C 函数。Python、Rust、Go、Java 和 JavaScript 都有办法调用 C 库。C 是各种语言之间的通用语。

为什么要学 C 语言

有两个实在的理由,面向的是不同的人。

如果你想从事系统软件开发,比如内核、驱动、嵌入式固件、数据库,C 就是这个领域的工作语言,这些方向的大多数招聘信息都会直接写明要求 C(通常还会同时要求 C++ 或 Rust)。如果读不懂 C,就很难为 Linux、PostgreSQL 或微控制器项目贡献代码。

如果你想更好地掌握自己已经在用的语言,C 会告诉你底层是什么。学过 C 之后,你会明白数组下标为什么从零开始,字符串究竟是什么,为什么按值传递大对象开销很大,栈和堆是什么,以及空指针到底指向哪里。这些概念在每种语言中都存在;只有在 C 里,它们是摆在明面上的,而不是被隐藏起来。

这个程序只有三行 C 代码,却完整地展示了变量是什么:位于某个地址上的、有名字的盒子。在大多数语言中,你甚至没法问出这个问题。

C 和 C++

C++ 于 1979 年以“带类的 C”起步,后来发展成现存规模最大的语言之一:类、模板、异常、运算符重载、STL、智能指针,以及一个比 C 的整份规范还要庞大得多的标准库。

两者在实践中的关系:

  • C++ 保留了 C 的语法,所以 if、for、while、运算符、指针和数组在两者中看起来都一样。
  • 大多数写得规范的 C 代码都能作为 C++ 编译,只有少数例外(比如 C++ 要求对 malloc 的返回值做类型转换)。
  • C++ 代码几乎从来都不是合法的 C 代码。

如果你打算两门都学,先学 C 是一个真正的优势:C++ 直接建立在 C 的内存模型之上,而 C++ 中最让人困惑的部分,指针、引用、拷贝语义、析构函数,都是在解决 C 清清楚楚展示给你的那些问题。

不过,C 在任何官方意义上都不是 C++ 的子集。它们是两个各自独立演进的标准,现代 C 还有一些 C++ 没有的特性(C99 引入的指定初始化器、restrict 指针和变长数组)。

哪个 C:标准版本

C 是标准化的语言,阅读老代码时,版本很重要。

标准年份值得了解的内容
C89 / C901989古老的基线。变量只能在代码块开头声明。
C991999// 注释、随处声明变量、通过 stdbool.h 使用 bool、long long
C112011线程、原子操作、更安全的库函数
C172018C11 的 bug 修复版,如今最常见的默认版本
C232024true/false/bool 成为关键字、nullptr、二进制字面量

本文档以 C17 为准,并在相关之处指出 C99 及以上的特性。编译器默认使用较新的版本,但你也可以明确指定:

gcc -std=c17 -Wall -Wextra hello.c -o hello

C 语言没有什么

理解 C 的一部分,是知道它缺少什么,因为几乎每个“我该怎么……”的问题,在这里的答案都和现代语言不同。

  • 没有字符串类型。 C 字符串是一个以零字节结尾的 char 数组。拼接两个字符串需要调用函数,还得操心目标空间够不够大。
  • 没有集合。 没有列表、映射或集合。你只有固定大小的数组和指针;哈希表要么自己写,要么链接一个库。
  • 没有异常。 函数通过返回一个特殊值来报告失败,比如 -1、NULL 或状态码,调用方需要自己检查。
  • 没有泛型和重载。 一个函数名只对应一个函数。所以标准库为三种不同类型分别提供了 abs、labs 和 fabs。
  • 没有命名空间或模块。 所有非 static 函数共享同一个全局命名空间,所以 C 库会给所有东西加前缀(sqlite3_open、png_read_info)。
  • 没有垃圾回收器。 每个 malloc 都需要一个对应的 free,忘了就是内存泄漏。

这些都不是疏忽。其中一些是 C 拒绝携带的运行时机制(垃圾回收器、异常展开、可增长的字符串),这在很大程度上正是它能装进只有 2 KB 内存的芯片的原因;另一些,比如命名空间和泛型,则是在 C 设计完成之后才出现的语言特性,为了保持语言小巧而没有加入。

缓冲区是 32 字节,因为是你决定这就够了。C 不会检查,这一行代码就体现了这门语言的全部性格。

C 语言难学吗?

C 很小,但不留情面。需要记的语法不多,一周就能把整门语言读完。花时间的是自律:记清哪块内存归谁所有,记住字符串只是以零结尾的字节,在使用指针之前检查它是不是空指针。

C 的难点大多不在概念上,而在于它没有护栏:编译器不会把你从越界写入或悬空指针中救出来,所以你会学会精确。(第一次学指针确实要花不少力气,这很正常,指针一章会慢慢讲。)这种精确是一种能带到你以后使用的每一种语言中的能力。

常见问题

C 语言是什么?

C 是一门编译型的通用编程语言,由 Dennis Ritchie 于 1972 年在贝尔实验室创造。它让你直接控制内存,并且与 CPU 实际执行的操作紧密对应,所以操作系统、设备驱动和数据库至今仍用它来编写。

C 语言现在用来做什么?

操作系统内核(Linux,以及 Windows 和 macOS 的部分组件),汽车、家电和微控制器中的嵌入式固件,SQLite 和 PostgreSQL 等数据库,CPython 和 Redis 等语言运行时和软件,以及供其他语言调用的高性能库。

2026 年还值得学 C 语言吗?

值得,原因有两个。它仍然是系统开发和嵌入式开发的语言,这是一个规模大、薪资高的领域。而且它能教会你内存、指针和栈到底是怎么工作的,这些知识会让你更好地掌握其他所有语言,因为它们大多数都是用 C 实现的。

C 语言和 C++ 有什么区别?

C++ 最初是“带类的 C”,保留了 C 的大部分语法,同时加入了面向对象编程、模板、标准库等大量内容。C 要小得多:没有类、没有异常、没有泛型。大多数合法的 C 代码都能作为 C++ 编译,反过来则不行。

Coddy 编程语言插图

和 Coddy 一起学编程

开始