Skip to content

C 从哪儿来:一门被真实工程难题逼出来的语言 ​

翻开不少 C 教程,第一页就是 int main 和一行 printf,好像这门语言是凭空从屏幕里长出来的。咱们这本不这么走:动键盘之前,先花几分钟认识 C 的来历。这不是掉书袋,后面每一章都要打交道的那位“翻译官”是什么出身、守的是谁家的规矩,答案全在这几分钟的故事里。

贝尔实验室,1972:被汇编逼出来的语言 ​

在开始咱们的 C 语言旅程之前,笔者想好好地讲讲 C 语言的故事。

请允许笔者碎碎念:笔者上大学才接触编程,好巧不巧,C 就是笔者的第一门编程语言,也是至今用得最多的语言之一,另一个是隔壁 C++,笔者也有一个仓库专门记录和讲解相关内容:TAMCPP

C 这门语言是被真实的工程难题逼出来的,跟课堂没关系,您没想到吧!

好了,让咱们回到 1972 年。地点是美国新泽西州的贝尔实验室,一位叫 Dennis Ritchie 的工程师在这里造出了 C。当然,您如果熟悉操作系统,就会知道这位大哥同时还是 Unix 的发明者。他的同事 Ken Thompson 用一门叫 B 的小语言给刚出生的 UNIX 写过最早的一批工具(内核那会儿还是汇编),而 B 又能一路追溯到英国的 BCPL。名字也懒得另起,顺着 B 往下数一位正好是 C。至于这一位是顺着字母表数的,还是顺着 BCPL 的字母数的,Ritchie 似乎也没特别说明(当然如果有熟悉编程语言历史的朋友真的深挖过,欢迎 PR 把这一段改了)。

咱们看实验室当时的难处,很实际:系统软件全靠汇编写,写得苦、读着更苦,还和特定 CPU 死死绑在一起。Ritchie 要的是一门“像汇编一样贴着机器、又像高级语言一样给人读”的语言。按他自己的回忆,当初没把“搬家到别的机器”当头号目标,可移植这层好处是后来才显出来的。1973 年,UNIX 内核(操作系统里最贴硬件、最核心的那部分)的大半就用这门新语言重写了;再往后 UNIX 真能从一种机型搬进另一种机型,靠的正是这身 C 打的底子。

屏幕上的英文,怎么变成能跑的程序 ​

读到这里,新手朋友心里多半冒出一个更实际的问题:屏幕上这几行英文,是怎么变成一个能跑的程序的?各位不管手上玩的是单片机、手机还是电脑,想没想过咱们的程序是怎么变成计算机听得懂的东西的?

这就要请出全书从头到尾打交道的关键角色编译器。咱们写下的 C 代码,说到底是写给人看的文本,一行行英文单词加符号;CPU 不认识这些,它只认自家指令集里的机器码,一条条用数字编码的指令(前面说的汇编,就是把这些数字指令写成人勉强能读的样子,不过笔者说真的,没多可读)。

人话和机器话中间隔着一次翻译,编译器干的就是这趟活:把整份 .c 从头到尾翻成目标 CPU 认识的指令序列,再和现成的库代码拼在一起,交出一份操作系统能直接加载运行的文件。咱们后面在终端里敲 gcc hello.c -o hello_gcc,就是在给这位翻译官派活,gcc 就是第 1 章两位主角里头一个亮相的。这套翻译拆成几步、每步的中间产物长什么样,第 3 章拿 -save-temps 逐站停车细看;眼下记住一句话就够:C 程序不是“跑”出来的,是“翻”出来的。

规矩来之前,一本书就是标准 ​

语言落地了,正经的规矩却等了十几年才来。中间那段时间,管用的“官方标准”其实是一本书:1978 年 Kernighan 和 Ritchie 合写的《The C Programming Language》,江湖人称 K&R。当然,他们玩的这套 C 就是大名鼎鼎的 K&R C,咱们后面还会撞见这个名字。

书写成什么样,写编译器的人就照着各自的理解去实现,理解稍有出入,细节就走样。走样攒了十来年,这门越来越大的语言,终于到了该立规矩的时候。第一版正式标准由美国国家标准协会 ANSI 在 1989 年定下,史称 C89;第二年国际标准化组织 ISO 接手,规矩从此挂在 ISO/IEC 9899 这个名下,第 1 章里咱们引用的 §6.10.8 条款,出处就是它。往后是一串年份:C99、C11、C17、C23,一代加一批特性、改一批规则。这串年份马上就要在第 1 章动真格。

标准是图纸,翻译官才是干活的人 ​

咱们把话说回来:标准本身一行程序也编不出来,把 ISO/IEC 9899 做成真能干活的软件,靠的是各家自己的实现。这个行当里资格最老的是自由软件基金会 GNU 项目的 gcc:1987 年发布第一个版本,名字原本是 GNU C Compiler,后来同一副骨架上能编的语言越接越多,才改叫 GNU Compiler Collection(编译器集合),Linux 世界的老功臣。

另一家是 LLVM 项目的 clang,2007 年前后由 Apple 起头,如今是 macOS 上的默认编译器,报错信息出了名地好读。同一份 ISO C 标准,两家各做各的实现,一段合格的 C 程序,按理在哪边都该编得过。“按理”两个字,笔者特意挑的。

两位翻译官,先来报个到 ​

耳听为虚,两位翻译官说得再热闹,咱们也得把它们请到跟前验明正身。--version 几乎是所有命令行工具的通用自检开关,敲下去,工具就得自报家门:

终端
$ gcc --version | head -2
gcc (GCC) 16.1.1 20260728
Copyright (C) 2026 Free Software Foundation, Inc.

$ clang --version | head -2
clang version 22.1.8
Target: x86_64-pc-linux-gnu

两位都到了场:GNU 家的 gcc,16.1.1;LLVM 家的 clang,22.1.8(这是笔者这台 WSL2 机器上 2026-08-29 抓的快照,各位机器上报出的数字更新更老都正常,能自报家门,就算数)。版本号不用背,眼下认下这张脸就行:从下一章起,全书所有的编译命令,主角就是这两位。

可两位一碰头,第一件事就露了馅:同一份源码、同一条命令行、同一台机器,gcc 认为自己在编 2023 年定稿的 C23,clang 认为自己在编 2017 年的 C17,前文说的“按理”两个字,当场就应了验。这不是谁坏了,是两家给“一个旗标都不给时按哪一年的 C 来编”设定的默认值压根不一样。怎么回事、怎么治,下一章“工具链体检”当面拆给咱们看。

参考资源 ​

  • The Development of the C Language——Dennis Ritchie 1993 年亲述 C 的诞生(本章“按他自己的回忆”的出处)
  • The C Programming Language(K&R, 1978)——十几年里“一本书就是标准”的那本书
  • gcc 与 clang 的真跑体检,第 1 章“工具链体检”接着看

87bb5f2 · 87bb5f2 · 2026-09-21