C 与 C++ 40 年的爱恨情仇


C 与 C++ 40 年的爱恨情仇

文章插图
作者 | cor3ntin
译者 | 弯月,责编 | 郑丽媛
头图 | CSDN 下载自视觉中国
出品 | CSDN(ID:CSDNnews)
以下为译文:
70年代初,贝尔实验室创建了C语言,它是开发UNIX的副产品 。很快C就成为了最受欢迎的编程语言之一 。但是对于Bjarne Stroustrup来说,C的表达能力还不够 。于是,他在1983年的博士论文中扩展了C语言 。
于是,支持类的C语言诞生了 。
当时,Bjarne Stroustrup明白编程语言有许多组成部分,除了语言本身,还有编译器、链接器和各种库 。提供熟悉的工具有助于语言被广泛接受 。在这种历史背景下,在C语言的基础上开发C++也是有道理的 。
40年后,C和C++都在行业中得到了广泛使用 。但是,互联网上的C开发人员认为C++是有史以来最糟糕的人类发明,而许多C++开发人员则希望有朝一日C语言灰飞烟灭 。
 
究竟发生了什么事?从表面上看,C和C++都可以满足相同的用例:高性能、确定性、原生但可移植的代码,可用于最广泛的硬件和应用程序 。
但是,更让C自豪的是它是一门低级语言,更接近汇编 。
而C++,从诞生第一天开始就充斥了各种奇怪的东西 。例如析构函数这个黑魔法 。自作主张的编译器 。尽管很早C++就有了类型推断功能,但是80年代中期的开发人员还无法接受这个概念,因此Bjarne Stroustrup不得不删除了auto,直到C++ 11又重新添加回来 。
从那以后,C++就不断加入各种工具来实现抽象 。很难说C++是一种低级语言还是高级语言 。从设计目的上来说,C++两者都是 。但是在不牺牲性能的情况下,建立高级抽象是很困难的 。于是C++引入了各种工具来实现constexpr、move语义、模板和不断增长的标准库 。
从根本上讲,我认为C信任开发人员,而C++信任编译器 。这是一个巨大的差异,单凭“两者的原生类型相同”、“while循环的语法相同”等简单一致是无法掩盖的 。
C++开发人员将有这些问题归咎于C,而C开发人员则认为C++过于疯狂 。我觉得站在C的角度看C++,这种说法也很正确 。作为C的超集,C++确实很疯狂 。一个经验丰富的C开发人员面对C++可能没有熟悉的感觉 。C++不是C,这就足以引发互联网上的激烈争论 。
然而,虽然我不喜欢C,但也没有权利取笑C 。尽管我有一定的C++经验,但用C编写过的代码少之又少,而且肯定是很糟糕的代码 。好的编程语言包括良好的实践、模式、惯用写法,这些都需要多年的学习 。如果你尝试用编写C++的方式写C的代码,或者用C的方式编写C++的代码,那感觉一定很糟糕 。即便你懂C,也不一定会C++,反之亦然,懂C++也不一定会用C编程 。
那么,我们是否应该停止说C/C++,为这两个不幸的命名而感到悲哀吗?也不至于 。
尽管C++的设计理念与C不一样,但是C++仍然是C的超集 。也就是说,你可以在C++转换单元中包含C的头文件,这样依然可以通过编译 。而这正是造成混乱的地方 。
C++不是C的扩展,它是由不同的委员会、不同的人独立设计的标准 。从逻辑上讲,喜欢C++理念的人会参与C++社区以及C++标准化的过程,而其他人可能会尝试参与C 。无论是C的委员会还是C++委员会,他们表达意图和方向的方式只能通过各自的最终产品:标准;而标准是众多投票的成果 。
然而,编译器很难知道它正在处理的是C头文件还是C++头文件 。
extern “C” 标记并没有得到广泛一致的使用,而且它只能影响修饰,而不会影响语法或语义 。头文件仅对预处理器有影响,对于C++编译器而言,所有内容都是C++转换单元,因此也就是C++ 。然而,人们依然会在C++中包含C头文件,并期望它“正常工作”,而大多数时候也确实可以正常工作 。
那么,我们不禁想问:
 
由不同地方的、不同的人开发的C++代码如何保持C的兼容性?恐怕很难 。
最近,一位同事让我想起了康威定律:
"设计系统的架构受制于产生这些设计的组织的沟通结构 。"
根据这个逻辑,如果两个委员不互相合作,则他们创造的语言也不会互通 。
C++维护了一个与C及其标准库的不兼容列表 。然而该列表似乎并未反映出许多C11和C18中添加、但在C++中不合法的功能 。更清晰的介绍请参见这个维基本科页面(https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B) 。
然而,仅仅列出两种语言之间的不兼容性,并不足以衡量二者的不兼容性 。


推荐阅读