为什么 C 语言能统治 50 年从“混乱代码”到“结构化编程”的革命

张开发
2026/5/14 17:12:27 15 分钟阅读
为什么 C 语言能统治 50 年从“混乱代码”到“结构化编程”的革命
C语言还在写操作系统程序员早就不爱它了可谁也绕不开它。最近翻Linux内核源码看到mm/memory.c里全是带volatile的指针一行行读下来没一个花里胡哨的语法就是地址加偏移、强转、解引用——好像50年前写的。问了几个做嵌入式的学长他们说智能手表固件、电机驱动、航天器飞控只要芯片小、没虚拟内存、不能崩写的全是C。不是不想换是换了就跑不动。很多人以为C能活这么久是因为“它快”。其实不对。FORTRAN也快汇编更快。问题是FORTRAN写不了中断处理汇编换颗芯片就得重写一半。C在1973年把Unix重写一遍不是因为它多牛而是它刚好卡在一个缝里人能看懂机器能直接执行中间不加一层骗自己的东西。B语言试过但没类型编译器没法算内存布局读个文件慢40%Pascal有类型可不让算指针硬件寄存器就摸不到。C的类型不是教你怎么编程是告诉编译器“这块内存必须这么排”。比如struct{int a; char b;}不是语法规定是跟CPU签的合同a占4字节b紧挨着占1字节对齐方式定了缓存行怎么填也定了。Pascal不让你动地址等于把合同撕了再好的类型系统也进不了内核。指针也不是bug是代理。你写*p 1不是在冒险是在说“请把数字1原封不动塞进p指向的那个确切地址”。ARM手册里写的寄存器地址0xFF00C里直接强转成结构体指针去读没有中间商没有解释器没有GC停顿。Python做不到Java做不到连Rust都得开unsafe块才能干这事——而unsafe块里面写的还是C那一套。函数调用看着简单其实是个大事情。每次调函数栈怎么压、参数怎么传、返回地址放哪C规定死了。这个规定不是为了好看是让操作系统能在毫秒级切任务。COBOL的PERFORM没栈帧FORTRAN子程序不能嵌套它们在单任务时代挺好一到多进程就卡壳。C的函数调用就是人脑分治和CPU流水线之间定的握手协议。有人说Rust能替代C可翻Rust标准库源码std::sync::atomic底层还是调GCC内置函数core::ptr一堆unsafe块里面解引用、取地址、强转类型全是C式写法。它不是推翻C是给C穿了件防弹衣关键地方还是得裸奔。Linux内核不用C不是讨厌类是虚函数表查表要跳转、异常要铺展开栈、new/delete可能卡在内存分配上——实时系统等不了那几十纳秒的不确定性。C标准几十年没加新语法。C89、C99、C11、C17改的全是边角漏洞比如C11加了_Atomic不是为了炫技是告诉编译器“这个变量可能被多核同时改请按CPU缓存一致性协议生成指令”。它不增加能力只堵洞。所以1995年写的glibc今天gcc13照样能链ABI没变过。C标准十年一变范式C标准五十年没动接口底线。嵌入式那边更直白。一个STM32F10364KB Flash20KB RAM跑不了Python解释器更别提JVM。你写一行print(hello)背后要带几百KB运行时。C编译出来就是一条mov r0, 1连库都不用裸机上电就能跑。这不是选择是物理定律内存不够就只能这么干。学C的时候老师总说“注意指针别越界”。后来才懂越界不是怕程序崩是怕你忘了自己正在跟真实硬件对话。地址不是数字是插座内存不是容器是电路板上的铜线函数不是模块是CPU流水线里的一个确定位置。C没教会我怎么写漂亮代码但它让我第一次知道键盘敲下去电流真正在哪条线上跑。C语言不是活成了经典是从来没死过。

更多文章