我已经被计算机科学入门一年多了,根据我的经验,似乎C和C ++都被认为是“超快速”语言,而其他语言(例如Python)和脚本语言则被认为是“超快速”语言。通常认为速度稍慢。
但是我也看到过很多情况,一个软件项目甚至一个很小的项目都会插入文件,其中某些数量的文件将用C编写,这些文件的数量m将用C ++编写。
(我还注意到,C ++文件几乎总是具有相应的头,而C文件则没有那么多)。但是我的主要研究目的是对何时在C ++上使用C合适,以及何时在C上使用C ++更好的情况有一个一般的直觉。除了(1)C ++是面向对象的而事实C不是,并且(2)语法非常相似,并且C ++是故意创建的,在许多方面都类似于C,但我不确定它们之间的区别是什么。在我看来,它们在几乎所有领域中都是(几乎)完全可以互换的。谢谢
#1 楼
在由于任何原因需要可移植汇编程序(实际上就是C)时,您选择C,
您的平台不提供C ++(C编译器很多
,您需要与只能与C交互的其他语言(通常是任何平台上的最低公分母)进行交互,并且您的代码仅包含接口,因此不值得放置基于C ++代码的C接口,
您侵入了一个开源项目(出于各种原因,其中很多人坚持使用C),而您不了解C ++。
在所有其他情况下,您都应该选择C ++。
评论
我还要补充一点,带有异常模型的C ++有时会带来更多麻烦,例如OS内核。至少那是我在阅读有关东西时得到的一般感觉。
–编码器
2011年10月10日,0:26
@SF:C是通用语言?那是新的。或者说,很老了。也许,如果您只与过去20年来从未学习过新语言的人交谈,但是我想说C知识不再是很普遍了。
– DeadMG
2011-10-10 12:44
@SF .:正如我在其他地方所写的那样,我参与的项目数量达到了数百万个LoC,与C项目相比,由于不可避免地存在着无处不在的宏黑客,因此看到的元数据很少。 (OTOH,在需要时创建EDSL的功能可能是您盒子中非常强大的工具。)至于C是通用语言:我宁愿坚持认为它是最低的公分母。而且我也不希望那些具有中等编程技能的人攻入OS内核。
–sbi
2011-10-10 12:45
@Max:我完全不同意。 C是一种无用的语言,除非某些无法克服的实际障碍阻止了C ++的使用。
– DeadMG
2011-10-12 15:45
@Buttons:是您提出了要求(“ C ++需要更多的内存”),因此应该由您来支持。而且,不,我并不是说C ++需要更少的内存。我的意思是,无论编译器是为您实现这些功能(虚拟函数)还是由您自己实现(功能指针数组),这些功能都是成本。
–sbi
2012年9月27日在9:41
#2 楼
有几个理由偏爱C。主要的原因是,使用C ++生成真正的小型可执行文件通常会更加困难。对于非常小的系统,无论如何您几乎都不会写很多代码,而C ++而不是C所需要的额外ROM空间可能会很大。对于非常小的系统,由于完全相同的原因,C会遇到问题,而汇编语言几乎是唯一合理的选择。 C真正有意义的系统大小范围很小,并且会不断缩小(尽管我会承认,相当缓慢)。另一个使用C的时间/原因是提供一组基本上可以从任何其他语言绑定到的功能。您可以通过将它们定义为
extern "C"
函数来用C ++编写这些函数,但是这样做会将这些函数限制为向世界展示本质上是C-life的“面孔”-类,重载函数,模板和成员函数等需要不适用。但这并不一定将开发限制在C上,在内部使用任何方式的C ++功能都是完全合理的,只要外部接口看起来像C。必须说@Toll的答案(举一个明显的例子)在大多数方面都有些倒退。合理地编写C ++通常至少会和C一样快,并且通常至少快一点。可读性通常要好得多,因为仅仅是因为您即使对于最琐碎的算法和数据结构,所有错误处理等,也不会陷入所有代码的雪崩之中。 t“解决语言的类型系统问题”,他们只是添加了一些基本功能,而没有模板的C和/或C ++几乎没有这些功能。最初的目的之一是提供类型安全的容器,但实际上它们远远超出了它— C根本没有提供。自动化工具在很大程度上也很容易引起人们的注意-确实,编写C解析器比编写C ++解析器要少工作,但事实是,最终并没有什么区别。很少有人愿意或能够为任何一个编写可用的解析器。因此,无论哪种方式,合理的起点都是Clang。
碰巧的是,C和C ++经常在同一项目中由同一个人维护,经常一起使用。这使得本来是很少见的事情:直接客观地比较总体上具有同等能力的人员(即完全相同的人员)用两种语言编写的代码的可维护性的研究。至少在链接研究中,一个结论是明确而明确的:“我们发现,使用C ++代替C可以提高软件质量并减少维护工作...”
评论
工具支持不是一个红鲱鱼。当然,如今我们有了we。但是,即使在大型IDE中,对C ++的工具支持也确实远远落后于其他语言。这是为什么?很简单,因为直到最近还没有clang(GCC从来没有替代方法)。直到大约半年前,如果您需要AST的C ++代码,则基本上运气不佳或没有数千美元(如果您购买了EDG前端)。
–康拉德·鲁道夫(Konrad Rudolph)
2011年10月10日在7:26
+1,作为记录,我定期为带有4KiB ROM的8位处理器编写C ++代码。
– avakar
2011年10月10日12:20
+1是一个很好的总体答案。我不理解(我没有任何经验),这是为什么(我想我们正在谈论嵌入式的?)在使用相同功能集的情况下,C编译器应产生比C ++编译器小的可执行代码?也许您可以提供一些参考?
–马丁·巴(Martin Ba)
2011年10月10日13:23
@Martin:最主要的是C ++包含异常处理,(至少通常)这会增加可执行文件大小的最小值。大多数编译器将允许您禁用异常处理,但是当您执行此操作时,结果将不再是C ++。我怀疑还有一个简单的事实,那就是许多C ++编译器供应商在产生最小的输出代码方面都没有那么努力。
–杰里·科芬(Jerry Coffin)
2011年10月10日15:04
“我们发现使用C ++代替C可以提高软件质量并减少维护工作量。”这是要记住的结论。
–斯蒂芬·罗兰(Stephane Rolland)
2012年8月14日19:25
#3 楼
C和C ++之间的差异已在此处详细列举。尽管有时候人们可能出于正当理由选择一个或另一个(例如,当C ++的额外功能带来了不希望的开销时,C ++用于OOP或C),但根据我的经验,这通常只是出于偏爱。处理此文件的人更了解和喜欢什么?我相信多数时候这就是原因,因为这两种语言确实都可以处理对性能至关重要的应用程序。(旁注:请查看Linus Torvads对为什么他更喜欢C而不是C ++的讽。我不一定同意他的观点,但是它使您了解了为什么人们会选择C而不是C ++,相反,出于这些原因,他的人会选择C。
评论
-1为Linus的咆哮。 :-{
–sbi
2011年10月10日下午6:18
为此不要减我一个!哈哈。我不同意Linus,但这是一个很好的例子,为什么人们可能会选择C而不是C ++(如果他们相信Linus的话)。我没有评论这些理由的合法性。
– Casey Patton
2011-10-10 7:49
@CaseyPatton:基本上,我会否决所有评论,这些评论都毫无评论地表达了这种夸夸其谈的言论,就好像这是一个真实的论点一样。
–sbi
2011年10月10日7:56
@Coder:您完全不需要了解STL实现。 STL的重点是您不必了解实现,除非您依赖标准未定义的行为,在这种情况下,为什么还要使用标准库?而且,由于开发人员的行为方式,不喜欢某种语言不只是一点点的疯狂。 C程序员的行为就像C是上帝赐予人类的礼物,并且过于盲目以至于看不到C ++提供从根本上和本质上直接优于C的功能(如RAII)的明显事实。
– DeadMG
2011-10-12 13:51
@Coder:如果最终对单个对象有太多的shared_ptrs导致内部计数器溢出,那么您做错了。该标准将为计数器指定最小大小(可能为32位),对于一个对象必须有超过20亿的shared_ptrs,这是不现实的。即使对象本身的大小为0,并且您拥有零开销的内存分配器,但您仍然在shared_ptrs上消耗了16GB的内存。
– DeadMG
2011-10-13 9:44
#4 楼
现有答案(截至发帖时)缺少的主要问题是选择。很简单。如果出于某种完全不合理的原因,您认为例外不值得开销,那么您就不必使用它们。您仍然可以拥有模板,RAII和Standard库,并且永远不会编写单个“ throw”。模板也是如此。如果由于某种原因,您认为它们导致不可挽回的(实际上很重要,这仅在嵌入式系统中)膨胀,那么您会感到惊讶-您也可以整天使用void *和sizeof(T)。没有什么可以迫使您使用C之上的任何C ++功能的。给定的功能。因此,考虑到C ++是C的全部,甚至更多,显然,C ++是一种高级语言。否则建议就像试图建议4大于5。
评论
按照您的推理,原始问题完全没有意义,因此应将其关闭。我想这个问题应该读成这样:什么时候我们应该限制自己使用C ++的C子集(使用纯C),什么时候使用完整的C ++才有意义。
–乔治
2011年10月10日19:18
这是正确的,但仅适用于一个人在自己的小项目上工作的情况。在现实生活中,几乎每个人都可能花费一半的时间来编写其他人的代码。不幸的是,大多数其他人对于这些完全不合理的原因“认为错误”。
– DarenW
2011-10-10 19:44
@DeadMG:分配程序如何在不引发异常的情况下报告错误?同样,添加更多功能并不一定就是改善复杂性或冗余性。
– Mankarse
2011年12月2日,下午4:30
@Mankarse:如果使用禁用异常的选项进行编译,则分配器要么终止程序,要么根据库的实现轻松使用空指针。
–赞·山猫
2012年1月25日20:56
@Mankarse:由于我在2007年的经验,当我尝试运行具有1 GB RAM并且没有交换空间的Linux系统时,无论如何,如果内存分配仍然失败,几乎所有台式机软件都会以可怕的可怕方式失败。
–赞·山猫
2012年1月26日上午7:06
#5 楼
有关C ++的事情使C程序员感到不安引擎盖下发生了很多魔术。构造函数,析构函数,虚方法,模板等可以使C ++代码比等效的C代码更容易编写和编写,但更难以理解和推理(取决于您对C ++及其关联约定的了解程度)。诸如
Foo newFoo;
之类的简单操作可能会调用许多代码,具体取决于如何定义了类Foo
(及其依赖的任何类)的构造函数。这也是为什么约定在遍历容器时写++it
而不是it++
的原因,因为后缀++
通常涉及昂贵的复制操作。 取决于您的工作,可能会有一些不小的开销,尤其是对于简单的任务。采取以下两个程序,第一个在C中,第二个在C ++中:
我在gcc 4.1.2上使用的SLES 10盒,前者生成的可执行文件大小约为9kb,而后者则占用了12.5kb的文件大小(无优化),几乎增长了28%。与C字符串库相比,C ++
string
类型在IMO上的使用要容易得多,C ++流比C流更灵活和可自定义,但是对于像这样的脑残代码,它们可能不值得开销。 与C相比,C ++是一种庞大的语言,具有一些极其复杂的语义。精通C ++比C花费更长的时间,这意味着许多声称知道C ++的人并不像他们认为的那样了解它。
关于C的事情使C ++程序员感到紧张
无论从哪方面讲,C都不是安全的编程语言。没有边界检查数组会导致很多可利用的行为(通过现已失效的
gets
函数,或通过带有scanf
和%s
转换说明符的%[
)。如果您尝试访问超出其当前定义范围的容器,C ++至少会为您提供引发异常的容器。 C给您的所有内容都是(如果您很幸运)细分违规。 与C ++为您提供的工具相比,C中的内存管理非常费力且容易出错。如果您要构建自己的容器,则负责对所有
malloc
和free
调用进行匹配,确保分配成功,在出现错误的情况下撤回任何部分分配,等等。在C ++中,您只需添加项目从容器中取出物品。如果有问题,将引发异常。 同样,与C ++提供的工具(即,异常)相比,C中的错误处理使人感到痛苦。真正有趣的是,当您分配了一堆内存然后在处理过程中碰壁时;因为必须退出,所以必须以正确的顺序释放该内存。使用C ++和RAII原理,这相对容易。
那么,什么时候可以在另一个上使用呢?可以用输入和输出以及性能问题来清晰地描述其行为,因此比起C ++,更喜欢使用C。否则,更喜欢C ++
评论
内存管理很复杂,在某些情况下容易出错,但是特别是在嵌入式世界中,使用完全静态的内存分配编写C程序通常是实际的。如果程序链接,则在运行时不会耗尽内存。这样的保证可以在C ++中轻松实现吗?
–超级猫
2014年2月20日下午5:12
#6 楼
Bjarne Stroustrup维护使用C ++的应用程序和公司的列表。您可以争论所需要的过程式编程还是OOP编程,但是您不能与过去20年的行业结果相抗衡。人们需要处理模块化组件。当然,您可以用C构建和维护模块化代码,但是C ++固有的OOP性质导致了出色的模块化,可测试性和代码重用性。C ++标准库(STL)本身仅包含矢量和地图,足以使用C ++。
C通常用于嵌入式系统。
我个人只会在只有某些具有C API的库的情况下使用C。
评论
您的最后一句话不是使用C的理由。您可以从C ++调用C库。
–user207421
2011年10月9日22:46
我将c ++用于DSP项目-不是c
–BЈовић
2013年9月7日在22:40
#7 楼
我要说的是,我之所以选择C而不是C ++的主要原因是仅当我不得不诉诸“这必须达到1000%稳定”的NASA之类的东西。C ++是〜当我们查看性能时,C为99%,效率更高。因此,即使在C语言中,您也可以编写比C ++更快的代码(您也可以使用C ++的子集,而没有例外,虚拟,流式传输,抽象等,但是基本上就是C),这是优化每件事的时间虽然STL已经过测试并且已经这样做了,但它会花费您超过可能实现的微不足道的性能提升或牺牲的代价,因为STL算法是由专家组编写的,并且您可能不是一切专家。
另一方面,C ++有大量的抽象。在某些情况下它们会泄漏,这会给您带来麻烦。很少有人知道100%的C ++陷阱,而我想知道更多的人知道所有C陷阱,因此编写解决方案以使团队的所有成员完全理解每个步骤在C语言中变得容易得多。
示例:您知道
shared_ptr<smthn>
何时将超出其引用计数,是否会引发异常?当Shuttle必须重新进入大气层时,这类事情并不酷,至少我猜是这样。此外,与错误代码相比,异常处理非常非常困难。很难看出该类是否是100%异常安全的,并且容易陷入泄漏。很多高级代表都表达了这一观点。
评论
究竟用哪种方式手动管理内存比“ std :: string之类的C ++”抽象“更稳定”?您是否曾经尝试指定一个平台,shared_ptr的计数器将在该平台上溢出?那将是一个有趣的平台。而且,如果您认为异常处理很困难,则应该看一下一段C代码,该代码检查每个函数调用中的每个可能的错误。 (我承认这样的代码很难获得,但这只是反对您的陈述的更强力论据。)对不起,但这确实是牛粪。
–sbi
2011年10月10日在6:24
@Lundin:““必须具有1000%的稳定性”的实现方式不允许首先进行动态内存分配”。是什么让您无法在C ++中做到这一点? (对我的知识和经验发表笼统的声明而不是提供任何论点是一种很便宜的修辞手法。)
–sbi
2011-10-10 7:08
@Lundin:很好,您已经开始提供论据,而不是夸夸其谈。但是他们很虚弱。您已经“忘记”了C ++(模板)的主要功能之一,该功能使代码更安全(因为它允许算法得以执行-从而在编译时失败,从而消除了运行时错误),但是说出您对所要判断语言的了解。出于充分的理由,这里以前曾批评将C ++还原为OO语言。 (此外,具有确定性破坏的类是一个很好的工具,对于管理除内存之外的其他资源很有帮助。)
–sbi
2011年10月10日上午10:11
@Lundin当然,如果您不希望动态分配,则不想使用std :: string。您将使用std :: basic_string
–吕克·丹顿(Luc Danton)
2011-10-10 12:29
@Coder:您认为您用这些证明什么?第一个完全是错误的代码(报告错误和返回值一样严重),第二个为RAII提供了手动清理的理由,每个半个体面的C ++开发人员都会为之欢呼,Joel和我一样尊重他,确实说了一些我非常不同意的话。他的单次单次出口塞住了一个不知情的老屁,他永远不会同意他25年前学到的东西被超越了。 (请记住,我是25年前,当时SESE是最先进的技术。)
–sbi
2011-10-10 12:35
#8 楼
C是具有更好语法的可移植程序集,可让程序员完全控制所有内容。另一方面,C ++做了很多时髦的魔术(虚函数,重载,自动转换等),可能当您要确保自己不满意时,这是不希望的:不要使用比您想使用的更多的内存
不要访问内存页willy nilly(vtable可以是随处可见)
不要意外地调用很多代码
,因为您专注于性能,所以想要一个非常简单的东西。毫不奇怪,这是非常有价值的。
如果您想要(并且我建议这样做),请阅读JSF编码准则,以了解在编写C ++用于军事航空电子控制时需要考虑的事项。您需要了解很多陷阱,并且可能会吸引您。 Bjarne是该文档的一部分,因此他知道该文档的内容。
另外,C就像被闪电击中的烫手巨魔一样进行编译。 OTOH C ++可能是由投资SSD公司的同一人赞助的。 :)
(个人而言,虽然我更喜欢C ++,但我也不喜欢它…….; ;-P)
评论
C有很多无法提供控制的功能。尝试编写高效的可移植代码,以将uint32_t与uint32_t相乘以产生uint32_t结果(产品的底部32位)。如果一个int是64位,则必须将至少一个操作数强制转换为uint64_t以防止发生未定义的行为,但是为了计算32位结果而必须强制转换为64位,这有点说得过去。 。
–超级猫
2014年2月20日下午5:18
不是。编译器会为您执行诸如寄存器分配之类的操作。我不能用C语言编写汇编中的可维护代码。
–指甲
2014年4月24日在15:00
#9 楼
(如果您对这两种语言有同样的熟悉程度)除非您的平台没有C ++编译器,否则请使用C ++。您可以编写C ++代码,而无需使用您不喜欢的语言的任何部分(没有类,异常,虚拟继承,您希望应用的任何个人限制),然后在将来的某个时候决定是否需要毕竟那些功能,那么您可以轻松地使用它们。 C ++不能阻止您编写C样式的代码。(给定的等效工具集和开发人员知识)只要平台具有C ++编译器,就没有理由选择C而不是C ++。您只需将自己局限于今天想要使用的语言的子集,同时为以后的扩展打开方便之门。
#10 楼
两种语言都很出色。我认为许多海报详细说明了每种海报的优势和各种用途。我将简单地添加以下内容:我认为C语言在4个方面都很完善:1)我认为这是第一次学习任何类型的编程时最好的语言[结合一些汇编和机器知识代码],2)非常适合编写驱动程序,3)嵌入式软件和4)最底层的系统软件。
C ++是一种面向对象的语言,但它也可以是过程语言(非常C)。如果您正在从事大型项目,基于GUI的软件,游戏软件以及其他类型的图形密集型软件,那么我发现C ++,Java甚至是Objective-C是您的最佳选择。但是,在许多命令行程序或系统软件中,您可能会发现C ++的性能与C相同或更好。
#11 楼
在我看来,此讨论中缺少一点:在C语言中,从库中提供稳定的二进制接口比较简单。在C ++中,不同的编译器使用不同的名称修饰,因此使用与库不同的编译器编译的库的使用者可能会遇到问题。使用C,二进制接口通常是针对该平台的标准化的。 br />我在Solaris上经常观察到这一点。发行版和不同的软件供应商通常将Sun Studio用作,尤其是在Sparc系统上,它通常可以提供更好的结果。男人开源项目是用gcc特定代码编写的。让人们一起工作可能会有些痛苦。
#12 楼
生成C代码时(例如在高级语言的实现中),C可能比C ++更可取。例如,有几种类似Lisp的编译器会发出C代码(例如Chicken,Scheme48 ...),但是我不知道会发出真正的C ++代码(我的MELT工具会发出C ++代码,但我不会将其称为真正的代码) C ++代码,它使用的C ++功能很少。)C代码也更容易半自动证明。诸如Frama-C的静态分析器(您可以在其中使用ACSL注释注释C代码,以帮助证明代码的人证明其原因)可用于C,但对于完整的C ++ 11而言则不适用。
评论
在C ++代码中通常使用C内联用于某些模块,这些模块需要高度优化,在硬件附近进行非常低级的工作,或者对于数据完整性乃至人身安全至关重要,并且需要进行审核并证明是正确的。除了在C中完成所有工作外,项目的大部分工作都可以利用C ++功能进行灵活的设计,同时在需要C的地方获得C的紧密性的好处。@kylben:许多C ++专家都会告诉您:(1)性能并不是降低到C的原因(也许避免使用虚拟化和其他一些妨碍优化的功能,但是非虚拟类并不是天生就效率低下的,而模板是功能强大的抽象工具,实际上可以提高效率-例如qsort vs std :: sort)。 (2)正确性的高度重要性是使用C ++(类型安全性,常量性,私有性,RAII使资源管理易于管理等)的原因。或者为此,首先使用Ada或其他东西。 >
@ Pubby8我不同意这一点。如果我正在处理.c文件,并且看到有人这样做,则倾向于在心理上标记他们不知道他们在做什么。例如,无需在C代码中将void *强制转换为另一种指针类型,这非常让人分心,并且是不了解C的人的典型代表。
@kylben :(您可能希望学习在评论答复中正确地解决其他问题,因此他们有机会实际看到他们。)“一个非常熟悉编译器如何将C转换为asm的程序员”对于C ++同样适用好。但这根本不相关:如果您想涉足asm,只需编写asm即可,而不是让编译器使用其他语言来创建它。毕竟,它的执行方式可能会随每次编译器更新而改变。
以我的愚见...对于您而言,您随时可以使用C,对我来说:C比C ++更简单易用... C ++看起来像是“带有类的C”,但现在已经不复存在了一种非常复杂的语言,其中包含虚拟构造函数和模板。