为什么大多数C中最大的开源项目?

我和朋友正在讨论,我们想知道为什么这么多开源项目决定用C而不是C ++。 Apache,GTK,Gnome等项目选择了C,但为什么不用C ++,因为它几乎一样?

我们正在寻找导致这些项目(不仅是我列出的项目,而且是所有C项目)的原因,而不是使用C而不是C ++。 主题可以是性能,易编程,调试,测试,概念等。

C非常便携,远远超过10年前的C ++。

此外,C在Unix传统中非常根深蒂固。 阅读“ Unix编程的艺术 ”,关于Unix和OO的一般内容 ,以及关于unix (包括C和C ++)的特定语言的更多内容 。

有许多反例:一切都基于Qt。

另外,在我的Debian测试系统上:

edd@ron:~$ apt-cache rdepends libstdc++6|wc -l 4101 

这是4101包,具体取决于基本的C ++库。 相比之下,libc6大约为14,982,大约为3.6。 但是,如果在开源领域没有任何C ++项目,那就不是了。

编辑: Thinko就我而言:由于C ++包也依赖于libc6,因此比例确实如此

(14982-4101)/ 4101 = 2.65

所以在C中实现的包大约是C ++中的两倍。

Eric Raymond的精彩书籍“Unix编程的艺术”对这个问题有一些反思 (整本书非常值得阅读论文或免费在线版本,我只是指向相关部分 – Eric参与了创造和引入“开源”一词,总是值得一读; -0)。

总结这一部分,Raymond声称“OO语言显示出一些倾向于让程序员陷入过度分层的陷阱”,而Unix程序员(以及扩展的开源程序员)则抵制了“厚胶”的陷阱。

在本书的后面部分,您会发现一些特别关于C ++的注意事项,例如“可能是C ++对OO的实现特别容易出错”。 无论你是否同意,整篇文章都值得一读(我在这里很难做到这一点! – ),并且参考书目丰富,指向许多其他相关的研究和出版物。

Linus Torvalds在C ++主题上多次肆虐 – 他使用C代替git,当然Linux内核主要是C:

  • 关于C ++和git (警告:首先要阻燃)
  • 从1998年开始接受Linus的采访

你可以很容易地找到更多这些,虽然它本质上是对这些事情有点躁动,但有一些有效的观点。

其中一个更有意思的(无论如何我坐在哪里)是观察到C ++编译器和库(并且在某种程度上)比相应的C编译器更多的错误。 鉴于两种语言相对复杂,这是有道理的。

它闻起来有点像“这里没有发明”(NIH)综合症,但是当你拥有整个Linux内核开发者基础时,你有时可以重新发明“正确的方法”。

许多项目在C ++标准化之前就开始了,所以C是明显的选择,后来的改变很难。 C在C ++之前已经标准化了大约十年,并且在更长的时间内更加便携。 因此,它在很大程度上是一个务实的决定,部分受到Unix大多数代码使用C的遗产的启发。

C ++很乱。 这是一个过于复杂的语言,如此复杂,只有少数人可以说他们知道所有的比特。 并且更少的编译器真正符合C ++标准。

所以我认为原因是简单性和可移植性。

如果你想要更高级和面向对象的编程,那么我认为C ++只是与像Python这样的其他人竞争。 (请注意,我用C ++编程了几年,速度很快,并且有一些来自高级语言的function,可以加速开发,而不是冒犯。)

我在我的时间里做过一些C ++项目,所有这些项目都以某种方式流下了眼泪。 在最基本的层面上,事实是人们不可信任。 他们不能信任编写好的代码,他们无法信任调试它,当他们不得不回来并在几周/几个月后再次修改它时,他们肯定无法理解它们。

C代码在C ++中没有很多奇怪的东西,这使得它很难调试(构造函数/析构函数,cpp_initialize()时间期间静态全局对象发生的任何事情等)。 这使得在开发和维护大型项目时更容易处理。

也许我是一个luddite,但每当有人在我身边说“C ++”时,我都会感到沮丧。

有些人提到了可移植性,但是在这一天,C ++的可移植性并不是一个大问题(它运行在任何GCC上运行,基本上都是什么)。 但是,可移植性不仅仅是架构到架构或操作系统到操作系统。 在C ++的情况下,它包括编译器到编译器。

我们来讨论ABI或应用程序二进制接口。 这基本上意味着“代码如何转换为汇编”。 在C中,当你写:

 int dostuff(const char *src, char *dest); 

您知道您在目标文件中创建了一个名为_dostuff的符号(C全局名称在结果程序集中都以下划线为前缀)。 但是在C ++中,当你写这个:

 int dostuff(const char *src, char *dest); int dostuff(const char *src, char *dest, size_t len); 

甚至:

 int dostuff(std::string src, std::string dest); 

所有投注立即关闭。 您现在有两个不同的函数,编译器必须生成每个函数,并且必须为每个函数指定一个唯一的名称。 所以C ++允许(我相信C不这样做) 命名mangling ,这意味着这两个函数可能被转换为_dostuff_cp_cp_dostuff_cp_cp_s (因此每个版本的函数使用不同数量的参数具有不同的名称)。

这个问题是(我认为这是一个巨大的错误,即使它不是C ++中交叉编译器可移植性的唯一问题)C ++标准留下了如何将这些名称修改为编译器的细节。 因此,虽然一个C ++编译器可能会这样做,但另一个可能会执行_cp_cp_s_dostuff ,而另一个可能执行_dostuff_my_compiler_is_teh_coolest_char_ptr_char_ptr_size_t 。 这个问题加剧了(总是找到一种方法将这个词隐藏到你说或写的任何东西),因为你不得不破坏名称而不仅仅是重载函数 – 如何处理方法和名称空间以及方法重载和运算符重载以及… (列表继续)。 只有一种标准方法可以确保您的函数名称实际上是您在C ++中所期望的名称:

 extern "C" int dostuff(const char *src, char *dest); 

许多应用程序需要(或者至少发现它非常有用)由C.Apache提供的标准ABI,例如,如果它是在C ++中的话,它几乎不能像跨平台那样容易扩展 – 你有考虑到特定编译器的名称损坏(以及特定的编译器版本 – GCC在其历史记录中已经改变了几次)或要求每个人普遍使用相同的编译器 – 这意味着每次使用a升级C ++编译器时向后兼容的名称修改方案,您必须重新编译所有的C ++程序。

这个post变成了一个怪物的东西,但我认为这说明了一个好点,我太累了,不能试图削减它。

作为一个不喜欢C ++而且会在任何时候选择C的人,我至少可以给你关于这个主题的印象。 C ++有几个属性使它没有吸引力:

  • 复杂的对象。 C ++有很多加速OO的能力,这使得语言变得非常复杂。
  • 非标准语法。 即使在今天,大多数C ++编译器都支持这样的怪癖,这些怪癖可以确保编译器之间的编译成功和正确。
  • 非标准图书馆。 与C库相比,C ++库几乎没有跨系统标准化。 我不得不处理与此相关的问题之前,我可以告诉你,使用C可以节省大量时间。

也就是说,C ++确实具有支持对象的好处。 但归根结底,即使对于大型项目,模块化也可以在没有对象的情况下完成。 当你添加一个事实,即基本上每个可能为任何项目贡献代码的程序员都可以编程C时,如果你需要编写接近金属的代码,那么选择其他任何东西都很难。

总而言之,许多项目跳过C ++并转向Python,Java或Ruby等语言,因为它们提供了更多的抽象和更快的开发。 当你添加它们支持从C代码编译/加载需要性能提升的部分的能力时,C ++失去了它可能具有的优势。

如果你看一下最近的开源项目,你会发现其中很多都使用C ++。 例如,KDE的所有子项目都是用C ++编写的。 但对于十年前开始的项目,这是一个冒险的决定。 当时C在forms上和实践中都是标准化的(编译器实现)。 此外,C ++依赖于更大的运行时,并且当时缺少良好的库。 你知道个人偏好在这样的决定中起着重要的作用,那时UNIX / Linux项目中的C工作人员远远大于C ++,因此新项目的初始开发人员更容易使用C语言。更大。 此外,任何需要公开API的项目都会在C中执行此操作(以避免ABI问题),因此这将是支持C的另一个参数。最后,在智能指针变得流行之前,使用C ++编程更加危险。 你需要更多熟练的程序员,他们需要过分谨慎。 尽管C具有相同的问题,但使用边界检查工具/库更容易调试其更简单的数据结构。

还要考虑C ++只适用于高级代码(桌面应用程序等)。 内核,驱动程序等不适合C ++开发。 C ++有太多“幕后”行为(构造函数/析构函数链,虚拟方法表等),在这样的项目中,您需要确保生成的机器/汇编代码不会有任何意外,并且不依赖于运行时图书馆支持工作。

毫无疑问,除了其他语言之外,还有一个重要的方面是C更容易与其他语言交互,因此,对于旨在广泛使用的库,即使是现在为此目的,也可以选择C.

举个例子我熟悉,工具包GTK +(在C中)具有强大的OCaml绑定,而Qt和Cocoa(分别在C ++和Objective C中)只有这种绑定的概念validation。 我认为将C语言之外的语言与OCaml接口的难度是其中一部分原因。

一个原因可能是GNU编码标准特别要求您使用C.我能想到的另一个原因是自由软件工具使用C比C ++更好。 例如,GNU缩进不像C一样执行C ++,或者etags不解析C ++以及它解析C语言。

我可以列出几个原因

  1. C代码生成更紧凑的对象代码。 尝试将“Hello World”编译为C和C ++程序,并比较可执行文件的大小。 今天可能不太相关,但绝对是10多年前的一个因素
  2. 使用C程序进行动态链接要容易得多。 大多数C ++库仍然通过C接口公开入口点。 因此,不是在C ++和C之间编写桥梁,为什么不在C中编写整个事物呢?

首先,一些最大的开源项目是用C ++编写的:Open Office,Firefox,Chrome,MySQL ……

话虽如此,还有许多用C语言编写的大项目。原因各不相同:它们可能是在C ++尚未标准化时开始的,或者作者对C更熟悉,或者他们希望C的学习曲线更容易会吸引更多的贡献者。

如果正确实现C非常快且非常便携,编译器就在那里

对于每个可用的编译器,C ++都是不同的,库不同意,标准不匹配。

您可以阅读Dov Bulka以查找cpp中不能做的事情,您可以在Google代码中阅读tesseract ocr,您可以阅读很多内容 – 其中大部分取决于您确定哪种代码语言优越。 你在哪里读到c在开源中有比cpp更多的源代码? 当然,你在ac论坛上看到了这一点。 那是在哪里。 转到其他一些编程语言。 进行相同的搜索,您会发现该代码具有更多开源。