众多编程语言都绕不开C语言,C语言拥有独特优势的原因

编程语言种类繁多,很容易让人挑花眼。Python多用于编写脚本,Java负责后端开发,Go主打并发场景,Rust侧重安全特性,Swift用于苹果平台开发,Kotlin适配安卓开发。往底层深挖就能发现,这些语言大多建立在C语言的基础之上。并非开发者刻意依赖它,而是底层运行环境本身就由C搭建而成。

C语言最特别的地方,是它和硬件之间的距离恰到好处。汇编语言紧贴机器,编写难度很高,更换芯片后代码基本无法复用。高级语言距离硬件太远,写下一行代码,底层发生的各类操作完全不受开发者掌控。C刚好处在两者中间,自带指针可以直接操作内存,支持位运算来对接寄存器,结构体能够把数据排布成硬件要求的格式。同时它又比汇编更容易上手,拥有函数、循环、基础数据类型这些能力。操作系统内核、设备驱动、嵌入式固件这类场景,要求精准管控内存资源与时钟周期,C语言刚好适配这类需求。Linux内核使用C开发已经三十多年,期间有人尝试改用C++重写,尝试之后发现收益很低。不是C++本身存在缺陷,只是在这类场景下C的实现方式更加直接。

科技

可移植性是C能够长久留存的另一关键因素。几乎所有平台都存在C编译器,从超级计算机到微波炉这类嵌入式设备,Windows系统或是各类实时操作系统都能支持。用标准C编写的程序,更换平台后重新编译就能直接运行。这里说的不是二进制层面的跨平台,而是源码层面可移植。当年Unix系统改用C重写,把C带到各式各样的硬件设备上,C跟着Unix一同传播。后续Unix分化出BSD、System V、Linux,C语言也随之扩散到各个领域。一门语言如果跨平台能力足够,并且很早就实现跨平台,就会成为行业默认选择。C并不是被设计成万能编程语言,它属于Unix的衍生产物,刚好赶上计算机普及的浪潮。

更深层的原因来自调用约定和ABI。操作系统对外暴露的接口都是C接口,动态库的符号遵循C符号规范,系统调用的封装也采用C函数形式。想要让不同语言编写的模块互相调用,最简单的方式就是走C ABI。Python的C扩展、Java的JNI、Go的cgo、Rust的FFI,全部都要和C交互。C相当于编程领域的通用交流语言。新语言哪怕设计得再精巧,如果需要对接操作系统、硬件或是其他语言,就必须兼容C规范。并不是C语法本身足够优雅,而是整个行业都认可这套标准,更换标准需要付出极高成本。

C程序极小的运行时经常被人忽略。编译后的C程序直接生成机器码,从main函数启动,不需要虚拟机、垃圾回收器,也不用复杂的初始化流程。不少编程语言自身的运行时就是用C开发。CPython解释器由C编写,JVM底层基于C++,Go运行时主体是Go加汇编,底层依旧依赖C,Node.js的V8引擎使用C++实现。这些语言让使用者不用直接写C代码,但语言的底层实现者绕不开C。业务开发时你可以避开C,但是开发编程语言的人不行。

C的语法体系十分精简,关键字数量有限,没有类、模板、异常机制,也不存在GC。这种精简带来一个优势,阅读C代码时,能大致预判编译器生成的机器码。不存在隐藏内存分配,没有后台隐式调用,运行时不会自动执行额外操作。对于需要严格控制延迟与内存占用的开发者,这种可预测性比安全特性更加重要。现代编程语言增加大量安全保护机制,但保护本身也会带来性能开销。C把选择权交给开发者,你可以写出运行速度极快的代码,也容易写出会崩溃的程序。这种自由是一把双刃剑,在系统开发场景,很多时候就需要这种灵活度。

C也存在竞争对手,Rust在系统编程领域发展势头很强,微软、谷歌、Linux内核项目都开始用Rust开发部分模块。不过Rust同样需要和C实现互操作,需要对外提供C接口,依托C的生态体系运行。C积累几十年的代码库、编译器、调试工具、网络协议栈,无法在短时间全部重写。大量老旧代码仍在持续运行,新芯片依旧需要支持C,相关标准也在持续更新。C本身偏保守的特性反而延长了它的生命周期。它不追逐新潮,语法改动很少,几十年前的老代码依旧能够编译运行。基础设施开发中,稳定远比新增语法特性重要。

大量编程语言无法脱离C,并不是因为它语法优美或是安全性最好。它处在硬件和抽象层中间的狭窄位置,任何需要和硬件交互的程序,都绕不开这一层。你可以用Python写业务,Go搭建服务,Rust开发驱动,但底层基础依旧由C支撑。新语言可以让使用者不用手写C代码,但没法让C彻底消失。短期内这个现状不会发生改变。

⚠️免责提示

本文内容整理于互联网,仅供参考,不构成任何投资、决策建议。部分素材来源于公开网络,如有侵权请联系平台进行删除处理。

网传计算机行业遇冷,为什么依旧大量人转专业进入计算机领域 返回列表