您还未登录! 登录 | 注册 | 帮助  

您的位置: 首页 > 软件开发专栏 > 开发技术 > 正文

撼不动的C语言!

发表于:2022-10-12 作者:布加迪 来源:51cto

作者 | Serdar Yegulalp

译者 | 布加迪

策划 | 云昭

数十年来C语言一直可谓是编程界的扛把子。Linux、Windows、Mac和许多其他操作系统的内核都能看到它的身影。C语言几乎可以写任何程序,在编程语言中的地位,德高望重。它甚至可能是有史以来最具影响力的语言。它的语法启发了许多其他语言,包括Cpp、Csharp、Java、JavaScript、Go、Perl等等。

自1972年以来,C编程语言一直是构建软件的主力语言之一。但是过去50年以来,已经涌现出数十种新语言,这些后辈语言的表现又如何?其中一些正在挑战C的统治地位,而另一些正在不断蚕食其地位。

撼山易,撼C语言难!在性能、裸机兼容性和普及性方面几乎没有语言能够击败C。不过仍有必要看看C与一些主流语言相比表现如何。本文介绍了它与C++、Java、C#、Go、Python及最新的语言Carbon的详细对比。

C与C++

C经常与C++相比较;顾名思义,C++是作为C的扩展而创建的。C++和C之间的差异很大,甚至可以说差异过大。

虽然C++在语法和方法上仍然酷似C,但提供了许多有用的功能,这些功能是C本身并不直接随带的:命名空间、模板、异常和自动内存管理等。一般,需要顶级性能的项目(比如数据库和机器学习系统)通常用C++编写,利用这些功能最大限度地发挥系统的性能。

此外,C++的步子比C迈得更大。即将发布的C++ 23带来了更多的功能,包括模块、协程和模块化标准库,以加快编译和更多的代码。相比之下,C标准的下一个计划版本C2x却没增加多少功能,而是专注于保持向后兼容性。

问题在于,C++中的所有优点也可能是缺点。软件功能使用的C++越多,引入的复杂性就越大,结果处理起来就变得越困难。如果开发人员只关注C++的一小部分,可以避免它的许多陷阱。甚至一些公司想要完全避免这种复杂性,比如说,Linux内核开发团队避免C++,虽然该团队将Rust视为未来增添内核功能的语言,Linux的大部分仍将用C语言编写。

C与Java

Java在几十年间依旧是企业软件开发的主力军,也是整个开发界的主力军。Java语法大量借鉴了C和C++。不过与C不同,Java默认情况下并不编译成本机代码。相反,Java的JIT(即时)编译器编译Java代码,以便在目标环境中运行。JIT引擎根据程序行为在运行时优化例程,从而实现了提前编译的C无法实现的多种优化。在适当的情况下,JIT编译的Java代码可以接近甚至超过C的性能。

而且,虽然Java运行时环境自动执行内存管理,但可以绕过这种处理。比如说,Apache Spark使用Java运行时环境的“不安全”部分来直接分配和管理内存,并避免JVM垃圾回收系统的开销,从而部分优化了内存中处理。

Java奉行“一次编写,随处运行”的理念,也使Java程序可以在对目标架构基本不需要调整的情况下运行。相比之下,虽然C已经移植到许多架构上,但任何特定的C程序可能仍需要定制,才可以在Windows与Linux上正常运行。

这种可移植性和强大性能的结合,加上庞大的软件库和框架生态系统,使Java成为构建企业应用程序的首选语言和运行时环境。

Java比不上C的一个方面是,C从不旨在竞争:它靠近硬件运行,或者直接与硬件打交道。

C代码被编译成机器代码,机器代码由进程直接执行。Java被编译成字节码,字节码是中间代码,JVM解释器随后将它们转换成机器码。此外,虽然Java的自动内存管理大体上是优点,但C更适合必须最优化使用内存资源有限的程序,因为它的初始占用空间很小。

C与Go

Go语法很大程度上归功于C,作为分隔符的花括号和以分号结尾的语句只是两个例子。精通C的开发人员通常可以直接上手Go,即使考虑到新的Go功能(比如命名空间和包管理)。

确保代码可读是Go的指导设计目标之一:让开发人员在短时间内尽快上手Go项目,并熟悉代码库。C代码库可能很难分析,因为它往往变成某个项目和团队所特有的一大堆宏指令和#ifdefs。Go的语法及内置的代码格式化和项目管理工具旨在防止这种根本性问题。

Go还有诸如goroutines(协程)和channels(通道)之类的附加功能,这些语言级工具用于处理组件之间的并发和消息传递。C需要这类功能由手工控制,或者由外部库提供,但Go直接就提供,因此构建需要它们的软件要容易得多。

Go与C最大的底层区别在于内存管理。默认情况下,Go对象可实现自动管理和垃圾回收。对于大多数编程工作来说,这非常方便。但这也意味着任何需要确定性处理内存的程序都将更难编写。

Go确实包括unsafe包,用来避开Go的一些类型处理安全机制,比如读写使用Pointer类型的随意内存。但unsafe附有警告:用它编写的程序“可能无法移植,且不受Go 1兼容性指导准则的保护。”

Go非常适合构建命令行实用程序和网络服务等程序,因为它们很少需要这种细粒度的操作。但是低级设备驱动程序、内核空间操作系统组件以及其他需要严格控制内存布局和管理的任务用C来创建再好不过了。

C与Python

如今只要一谈起软件开发,Python似乎总是避不开。毕竟,Python是“第二好的语言”,无疑是用途最广泛的语言之一,拥有成千上万的第三方库。

Python强调更注重开发速度而不是执行速度,这也是它与C最大的不同之处。一个程序可能需要一个小时才能用另一种语言(如C)组装起来,但仅需几分钟内即可用Python组装起来。另一方面,该程序在C中执行可能需要几秒钟,但在Python中运行可能需要一分钟。

一个好的经验法则是,Python程序运行起来通常比C程序慢一个数量级。但是对于现代硬件上的许多任务来说,Python足够快了,这是它得到采用的关键。

另一个主要区别是内存管理。Python程序完全由Python运行时环境管理内存,因此开发人员不必担心分配和释放内存方面的细节。但开发人员的轻松是以“运行时性能”为代价。

编写C程序需要严格注意内存管理,但由此生成的程序对纯粹的机器速度而言却堪称标准。

谈完区别,二者在底层却有深层的联系:参考Python运行时环境是用C编写的。这让Python程序可以包装用C和C++编写的库。第三方库组成的Python生态系统有相当一部分(比如用于机器学习的第三方库)都以C代码作为核心。在许多情况下,这不是用C还是用Python的问题,而是涉及应用程序的哪些部分应该用C编写、哪些部分应该用Python编写。

如果开发速度比执行速度更重要,而且如果程序的大部分高性能部分可以被隔离到独立的组件中(而不是分散在整个代码中),那么纯粹的Python库或结合Python库和C库都是比单独的C更好的选择。但在其他方面,C仍占统治地位。

C与Carbon

C和C++的另一个最近的竞争者是Carbon,这是一种目前正在大力开发的新语言。

Carbon旨在成为C和C++的现代替代品,它有简单的语法、现代工具和代码组织技术,以及解决C和C++程序员长期面临的问题的方案。它还旨在提供与C++代码库的互操作性,因此可以增量迁移现有代码。这一切都受到欢迎,因为与最近开发的语言相比,C和C++在过去的工具和流程显得很原始很简陋。

那么有何缺点呢?目前,Carbon是一个试验项目,尚未准备好用于生产环境。

甚至没有一个切实可行的编译器,只有在线代码浏览器。Carbon还需要一段时间才会成为C或C++的实用替代品,如果真可以替代的话。

原文链接:

​https://www.infoworld.com/article/3402023/why-the-c-programming-language-still-rules.html