【IT168 评论】C语言,从20世纪70年代设计并实现之初,就注定是带有强烈工程师文化,而缺乏一些学术气息的语言。它的许多细节设计,都带有强烈的实用化痕迹。C语言因Unix操作系统而生,是Unix系统的母语。这导致在这个广泛应用的操作系统上开发,必须通过C语言的形式和系统进行交互。这不仅影响了Unix一个平台上的软件,也影响了后来世界上最大的桌面系统Windows,以及越来越多的嵌入式平台。
由于大部分应用软件最终都需要和操作系统打交道,所以用来开发应用软件的语言,绝大部分也需要利用C语言完成和操作系统的通讯。这个世界上绝大部分流行的编程语言,都选择了用C语言来实现其编译器或解释器,以及基础部分的运行时库。无论C语言设计本身有何种缺憾,在今天,它已无可取代。
到了今天,大部分程序员不再需要逐个时间周期地去抠程序的性能。不需要刻意追求速度最快、最节省系统资源的软件。不需要写那些和系统内核紧密联系的程序。但C语言在此之外,依然有其重要的应用领域。我们可以把它作为对最终机器模型的高层次的统一抽象工具,而不必考虑机器环境的差异。经过30多年的发展,证明了C语言的确是对经典机器模型的非常好的表述。仅仅通过增加一个非常薄的胶合层就得到了清晰简洁的设计。正是这一点,使得C语言在计算机硬件高速发展的几十年中,一直生机勃勃。
我们在讨论C语言时,其实不仅仅涉及了C语言本身那用三十几个保留字构成的精简的控制结构和简约的语言特征。还包括了一套对#号打头的预处理部分(尤其是基于文本替换的宏处理),以及某些惯用的源代码组织方式(例如所有的接口定义被定义在后缀为h的文件中,并通过预处理方式替换进源代码)和基本的程序库。
这几部分语言核心之外的部分相对独立,以致于使用C语言开发并不一定使用标准化的那些东西。C语言对运行时环境的依赖是非常小的。
而编译预处理器又使得语言富有弹性,甚至可以写出违背C语言哲学的代码。著名的IOCCC大赛展示了许多常人无法理解的C代码。但实际上,C语言主张代码清晰,表里如一。开发者和维护者都能很容易地预测每一行代码背后的行为。避免存在一些阴暗的角落藏着一些罕见的用法导致程序运行时出现诡异的行为。C语言在发展过程中一直坚持着最小意外原则。而这一点,正是C语言的,著名发展分支C++所偏离的东西。
C语言并不是绝对意义上最快的语言,但是它的效率非常好,在切合大部分机器模型并给出统一抽象的基础上,几乎没有其他语言做得更好了。这也是C语言哲学的一部分:在统一硬件抽象模型的基础上,尽可能地利用所在硬件环境的一切资源。有时候C语言程序员会走向某种极端,追求语言细节的优化,觉得某种代码的组织方式会比另一种方式更高效,但几乎总是错的。优化取决于对具体硬件的理解,以及对编译器如何翻译这些代码的了解,但这正是设计C语言想避免的东西。我们不必去争论在语句级上每行代码精确开销的优劣。
同时,C语言的另一设计哲学就是让每行C代码尽量准确地对应相当数量的目标机器码。这使得程序员更为容易地理解程序的运行过程。让程序员脑海里实时地做一个源代码到最终控制流程的映射。基于这个思想,C语言一直没有增加对结构进行操作的操作符(而C++中把类或结构模拟成原生类型的做法相当普遍),甚至于inline关键字也迟迟没有被标准化(inline出现在C99标准中,但这个最新的C语言标准并没有被广泛接受),正是因为它某种程度破坏了这一点。
C语言在坚持以上几点理念时,并非突出某个方面(比如追求性能),而是同时兼顾。