为什么我没有抛弃C而选择其他语言?|弯月

作者 | 科斯佳·希什科夫

翻译 | 弯月面编辑器 | 欧阳舒立

出品 | CSDN(ID:CSDNnews)

以下为译文:

虽然C不是我学的第一门语言,也不是最后一门语言,但我还是很喜欢C,当我需要写程序的时候,我的第一选择就是C。同时,我会关注现代编程语言及其趋势,我已经用 Rust 编写了自己的商业爱好项目。那么为什么我不放弃 C 语言而改用另一种语言呢?我对 C++ 有什么看法?

为什么 C 不是最好的语言?

首先,这个世界上没有最好的编程语言。每种语言都有独特的优势和用例,因此虽然您可以在 Excel 中编写光线追踪程序,但最好使用其他语言。因此,我们都需要了解编程语言的局限性,不要抱怨 Web 服务器不是用 Fortran 编写的,或者基本上没有应用程序使用 Perl 或 C++ 作为其内部脚本语言。我认为不理想的 C 语言方面包括以下方面(除了 C 更老且欠发达,当然与个人喜好有关)。

其次,有时 C 语言不够明确。例如,* 可以是二元乘法运算符、一元解引用运算符,也可以用于声明指针。

此外,在某些情况下它不够安全,例如在没有运行时检查的情况下越界访问数组的极其常见的错误,这甚至无法与 Borland Pascal 相比,更不用说更现代的编程语言了(尽管你会转向出于性能原因将其关闭)。这个编译选项)。此外,指针很难保持一切井井有条。再加上其他一些情况,例如调用函数而不事先声明原型,很容易将错误类型的参数传递给函数。

最后,C 的标准库非常有限。一些编程语言甚至有一个开箱即用的 web 服务器(或者至少是构建 web 服务器所需的所有模块),但 C 标准库甚至没有 web 服务器的容器。

为什么我还是喜欢C?

不过,我真的很喜欢 C,因为它是一门简单的语言。从某种意义上说很简单,很容易表达你的想法和期望。

例如,假设两个数组有两个偏移量,其中一个可以是负数。如果用 C 语言编写,则可以写成:

arr[off1 + off2]

在 Rust 中,它需要写成:

arr[((off1 as isize) + off2) as usize]

总的来说,C 的循环也比 Rust 的迭代器组合更简洁(当然 Rust 允许前一种方式,但 linter 不满足,它会建议你改用迭代器)。同样,memset 和 memmove 也是非常强大的工具。

在大多数情况下,您可以预测编译的结果,即对象在内存中是如何表示的,以及如何以不同的方式理解编译的结果(这在 C 标准的较新版本中变得更加困难,这需要 Blame C++,我稍后会详细介绍)。此外,您很清楚函数调用的结果等等。由于这个原因,C被称为可移植的汇编语言,所以我非常喜欢C。

拿汽车打个比方吧,C语言就像一辆跑车,有手动变速箱,能提供最好的性能,但如果不熟悉离合器和齿轮的操作,很容易损坏变速箱,甚至可能损坏发动机,当然,如果你踩油门太多,也有可能冲出路面。但是,与自动变速箱相比,这款车的发动机功率更大,您可以预测性能并炫耀汽车,这是其他车辆无法做到的。

这与 C++ 有什么关系?

现在,让我们谈谈 C++。实际上,我并不讨厌 C++。我不能否认 C++ 比 C 有两个优势:

另一方面,C++ 有两个我非常不喜欢的特性。

首先是语言的整体性质。其他编程语言拥有的流行特性最终会进入 C++。所以每隔几年,C++ 标准就会添加新的特性。最终,语言变得有点怪异,没有人能完全掌握,而且很多特性都是从其他语言中复制过来的。基本上,每个人在写代码时,都会选择 C++ 的一个子集,而忽略其他特性的存在。此外,对于我们应该使用哪个 C++ 版本的功能,没有标准的方法。Rust 在包的范围内提供版本管理。据我所知,C++也曾尝试引入“代际”的概念来实现相同的功能,但没有成功。我经常听到有人自己编写 C 编译器,但我从未听说过有人编写 C++ 编译器。

其次,实际上C++不仅是一种语言,而且还是一种元语言(即模板)。我了解 C++ 是如何创建的,并同意它比 C 预处理器更好地处理与类型无关的代码。但实际上,它生成的代码很糟糕。原本“头文件只包含声明,实现放在编译后的代码中”,现在变成了“头文件包含了项目会用到的所有代码”。我不喜欢过于冗长的编译时间,但这只会让事情变得更糟。

最后,我认为 C++ 的出现给 C 带来了限制和不利影响。我不是在谈论 C/C++ 或 C 与 C++ 有什么共同之处,我说的是对标准和 C++ 都有不良影响的耦合。编译器。一方面,C++ 建立在 C 之上,因此得到了极大的发展;另一方面,如果 C++ 中不存在大多数从 C 中遗留下来的特性会更好(当然,C++ 设法通过过时的一些 C 特性已被逐步淘汰,但对旧特性的支持仍然存在)。但是,C++24能否在C++21的基础上发展成独立的编程语言呢?大多数过时的功能可以扔掉吗?我对此表示怀疑。

C++ 编译器对 C 的影响

实际上,C 被视为没有某些特性的 C++。例如,微软的 C 编译器直到 2015 版才支持 C99 功能(即使在那时,它也支持以 bug-fix-bug 方式的兼容性,因为客户可能会惊讶地发现可变参数宏确实有效)。但是,无论是在标准编译器还是其他编译器中看到相同的方法,这些都是相关的问题。

主要问题是 C 和 C++ 标准都是根据编译器开发者的反馈编写的,而且大多数是 C++ 开发者(有些人对现实世界的编程一无所知,他们还认为现实世界的实践与完全同意我自己的观点是令人窒息的操作)。虽然我也不遵循标准的开发程序,但我很确定 C99 和后来的许多令人讨厌的特性来自那些编译器开发人员。他们只考虑 C++,并以简化编译器的名义将这些特性强加于 C。

当然,我指的是“未定义的行为”以及编译器如何处理它。这已成为一个主要的癌症(只要您的代码依赖于二进制补码算法脚本错误是什么原因,就假定它具有未定义的行为,并且编译器会丢弃整个代码块)。

在我看来,以下四种行为是不可取的,但前两种并非不能接受:

由于 C++ 比 C 更高级(虽然它具有 C 的许多特性,但不推荐使用 reinterpret_cast 代替强制转换,使用引用代替指针等),所以不要期望 C++ 程序员表现得像 C 程序员理解底层代码。当然,由于 C++ 程序员占绝大多数,而且 C/C++ 耦合极为普遍,因此 C 编译器经常被扩展以支持 C++,并用 C++ 重写以适应其复杂性。所以不幸的是,你必须使用 C++ 编译器来编译 C 编译器(幸运的是,我们也有纯 C 编译器,如 LCC、PCC 和 TCC)。

总结

总的来说,我喜欢 C 的中级位置,它可以做一些低级的实现,比如轻松操作内存脚本错误是什么原因,同时享受高级语言的好处。另一方面,我对 C++ 的强烈不满来自于它的设计选择,而这些设计影响了 C 标准和编译器。

至少我不可能用 C90 特别版替换 C90 并假装原始版本不存在。

原文链接:

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论