以下是C ++的好处
- C ++提供了他们所要求的特定功能
- 他们的C编译器几乎可以肯定是C ++编译器,因此不会产生软件成本问题
- C ++和C一样可移植
- C ++代码可以和C一样高效(或多或少)
是否有任何具体的原因和特定的情况,即必须在C ++上使用C?
引用此问题:C语言中的泛型库
不能重复,因为这个问题是在询问语言限制,而不是在/不应该学习一种语言。
Peter Kirkham的帖子对我来说是最有用的信息,特别是关于我没有考虑过的C99问题,因此我接受了。感谢所有其他参加者。
以下是C ++的好处
是否有任何具体的原因和特定的情况,即必须在C ++上使用C?
引用此问题:C语言中的泛型库
不能重复,因为这个问题是在询问语言限制,而不是在/不应该学习一种语言。
Peter Kirkham的帖子对我来说是最有用的信息,特别是关于我没有考虑过的C99问题,因此我接受了。感谢所有其他参加者。
Answers:
这是由我对当前问题的回答所提示的,该问题询问有关C的泛型库-发问者特别声明他们不想使用C ++。
C是一种完整的编程语言。C不是C ++的任意子集。C根本不是C ++的子集。
这是有效的C:
foo_t* foo = malloc ( sizeof(foo_t) );
要使其作为C ++进行编译,您必须编写:
foo_t* foo = static_cast<foo_t*>( malloc ( sizeof(foo_t) ) );
这不再是有效的C。(您可以使用C样式的强制转换,在这种情况下它将在C中编译,但是大多数C ++编码标准以及许多C程序员都避免使用它;在Stack Overflow上见证“不要强制转换malloc”注释) 。
它们不是同一语言,并且如果您有C中的现有项目,则不想仅使用库就用另一种语言重写它。您可能希望使用可以使用您所使用的语言进行接口的库。(在某些情况下,可以使用一些extern "C"
包装函数来实现,这取决于C ++库的模板/内联方式。)
在我正在处理的项目中获取第一个C文件,如果您只交换gcc std=c99
以下内容,就会发生这种情况g++
:
sandiego:$ g++ -g -O1 -pedantic -mfpmath=sse -DUSE_SSE2 -DUSE_XMM3 -I src/core -L /usr/lib -DARCH=elf64 -D_BSD_SOURCE -DPOSIX -D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112L -Wall -Wextra -Wwrite-strings -Wredundant-decls -Werror -Isrc src/core/kin_object.c -c -o obj/kin_object.o | wc -l
In file included from src/core/kin_object.c:22:
src/core/kin_object.h:791:28: error: anonymous variadic macros were introduced in C99
In file included from src/core/kin_object.c:26:
src/core/kin_log.h:42:42: error: anonymous variadic macros were introduced in C99
src/core/kin_log.h:94:29: error: anonymous variadic macros were introduced in C99
...
cc1plus: warnings being treated as errors
src/core/kin_object.c:101: error: ISO C++ does not support the ‘z’ printf length modifier
..
src/core/kin_object.c:160: error: invalid conversion from ‘void*’ to ‘kin_object_t*’
..
src/core/kin_object.c:227: error: unused parameter ‘restrict’
..
src/core/kin_object.c:271: error: ISO C++ does not support the ‘z’ printf length modifier
src/core/kin_object.c:271: error: ISO C++ does not support the ‘z’ printf length modifier
总共69条错误行,其中4条是无效的转换,但主要是C99中存在的功能,而C ++中没有。
并不是说我正在使用这些功能来获得乐趣。将其移植到另一种语言需要大量工作。
因此,提出以下建议显然是错误的
[a] C编译器几乎可以肯定是C ++编译器,因此不涉及软件成本
将现有的C代码移植到C ++的过程子集时,通常会产生重大的成本影响。
因此,建议“使用C ++ std :: queue类”作为问题的答案,以寻找在C中使用队列的库实现比建议“使用目标C” 和“使用JNI调用Java java.util.Queue类”要晚。或“调用CPython库” -目标C实际上是C(包括C99)的适当超集,并且Java和CPython库都可以直接从C调用,而不必将无关的代码移植到C ++语言。
当然,您可以向C ++库提供C外观,但是一旦这样做,C ++就和Java或Python一样。
我意识到这既不是专业的答案,也不是一个特别好的答案,但是对我来说,这仅仅是因为我真的很喜欢C。C小而简单,我可以将所有语言都融入我的大脑,对我来说C ++似乎一直是一个巨大的混乱局面在各个层面上,我都很难过。因此,我发现,每当我编写C ++时,与在编写C语言时相比,花费更多的时间进行调试并将头撞在坚硬的表面上。我再次意识到,很多原因很大程度上是我自己的“无知”造成的。
如果可以选择的话,我将使用python(或可能的C#)编写所有高级内容,例如接口和数据库交互,以及使用C编写的所有必须快速的内容。对我来说,这给了我最好的东西。用C ++编写所有内容,感觉就像世界上最糟糕的事情一样。
编辑: 我想补充一点,如果您将要由几个人从事一个项目,或者如果优先考虑可维护性,那么我认为具有几个C ++功能的C在很大程度上不是一个好主意。关于什么构成“几个”以及在C中应完成哪些位以及C ++中的哪些位最终导致精神分裂症代码库,将存在分歧。
在某些实际环境中,例如底层嵌入式系统,根本不支持C ++。这样做有一个很好的理由:C很容易满足这些要求,那么为什么要使用更大的功能呢?
我讨厌用C ++编程。
可能有两个原因:
当我可以摆脱它时,我仍然更喜欢用C ++编写,总的来说,我认为好处多于缺点。但是我也可以看到在某些情况下使用C的论点。
关于嵌入式编程,性能和内容有很多争论,我不买。在这些方面,C ++很容易与C相提并论。然而:
就在使用C ++编程超过15年之后,最近我一直在重新发现C根。我必须说,尽管C ++具有使生活变得更轻松的良好功能,但也存在很多陷阱和一种“总是有更好的做事方式”。您从未真正对所完成的解决方案感到满意。(不要误会我的意思,这可能是件好事,但大多数时候不是)。
C ++给您无限的射击能力。可以说这很好,但是总会以某种方式最终使用过多的东西。这意味着您正在用抽象,通用性等“好的”和“漂亮的”层来掩盖您的解决方案。
我回到C的发现实际上是又一次有趣的编程。花了很多时间进行建模和思考如何最好地使用继承,我发现用C进行编程实际上使我的源代码更小,更易读。这当然取决于您的自律水平。但是,在直接代码中放置太多抽象是很容易的,这实际上并不需要。
infinite gunfire
,是的,如此真实。我们的脚从字面上发抖:)
C的主要优势在于,当您查看某些代码时,您可以看到真正的情况(是的,预处理器:使用-E进行编译,然后您可以看到它)。当您查看某些C ++代码时,常常会发生一些不正确的事情。那里有基于范围或由于赋值而隐式调用的构造函数和析构函数,您有运算符重载,即使没有被严重滥用,它们也可能具有令人惊讶的行为。我承认我是一个控制狂,但是我得出的结论是,对于想要编写可靠软件的软件开发人员来说,这并不是一个坏习惯。我只想有一个很好的机会说我的软件完全可以完成预期的工作,同时又不会让我的肚子感到不适,因为我知道其中仍然存在很多错误,因此我不会
C ++也有模板。我讨厌和爱他们,但是如果有人说他或她完全理解他们,我就称他为骗子!这包括编译器作者以及定义标准所涉及的人员(当您尝试阅读该标准时,就会很明显)。涉及到如此多荒谬的误导性极端案例,以至于在编写实际代码时根本不可能将它们全部考虑在内。我喜欢C ++模板的强大功能。您可以与他们一起做的事真是令人惊奇,但它们同样会导致人们无法(无法)想象到的最奇怪,最难发现的错误。这些错误实际上发生了,甚至很少发生。阅读有关解决C ++ ARM中模板的规则的信息,几乎使我大跌眼镜。这让我感到很浪费时间,不得不阅读几千个字符长的编译器错误消息,为此我已经需要10分钟或更长时间才能了解编译器实际向我要什么。在典型的C ++(库)代码中,您通常还会在头文件中找到大量代码以使某些模板成为可能,这反过来又使编译/执行周期极其缓慢,即使在快速的计算机上也是如此,并且当您更改某些内容时,需要重新编译大部分代码那里。
C ++也有const陷阱。您可以在大多数琐碎的用例中都避免使用const,否则您迟早将其抛弃,或者在其演化时必须重构代码库的大部分,尤其是当您要开发漂亮而灵活的OO设计时。
C ++具有比C强的类型,这是很棒的,但是有时候我觉得当我尝试编译C ++代码时,我正在喂Tamagotchi。我通常从中得到的大部分警告和错误并不是我确实在做不起作用的事情,而仅仅是编译器不喜欢我这样做的事情,而没有在此处强制转换或添加一些额外的关键字,那里。
这些只是为什么我不喜欢C ++的原因,因为我不喜欢仅使用一些据称可靠的外部库编写的软件。当您与其他人一起编写代码时,真正的恐惧就开始了。他们是非常聪明的C ++黑客还是幼稚的初学者,几乎没有关系。每个人都会犯错误,但是C ++故意使他们很难发现,甚至更难发现。
使用C ++时,您会一直迷失而不必一直使用调试器,但是我希望能够在我的脑海中验证我代码的正确性,而不必依靠调试器来查找我的代码在我无法预期的路径上运行。实际上,我实际上试图在脑海中运行所有代码,并尝试使用它具有的所有分支,甚至在子例程中也是如此,并且仅偶尔使用调试器,只是为了查看它在我准备的所有舒适场所中运行得如何。编写和执行如此多的测试用例以至于所有代码路径都已与各种奇怪的输入数据结合使用,这是完全不可能的。因此,您可能不知道C ++程序中的错误,但这并不意味着它们不存在。C ++项目越大,我越有信心,即使它与我们手头的所有测试数据都能完美运行,也不会有很多未被发现的错误。最终,我将其丢弃,并以其他某种语言或其他语言的组合重新开始。
我可以继续,但我想我现在已经说清楚了。所有这些使我在用C ++进行编程时感到工作效率低下,并使我对自己的代码的正确性失去信心,这意味着我将不再使用它,而我仍然使用并依赖于我编写了20多个代码的C代码几年前。也许仅仅是因为我不是一个优秀的C ++程序员,或者可能是因为我在C语言和其他语言中表现出色,才使我认识到在C ++方面我实际上是个傻瓜,而我将永远无法完全理解它。 。
生命短暂...
在低级嵌入式环境中,一些“软件工程师”将具有EE背景,并且几乎不掌握C。C++更复杂,其中一些人只是害怕学习新语言。因此,C被用作最低公分母。(在您建议摆脱这些家伙之前,它们至少和不了解硬核模拟方面的CS专业一样重要。)
从继承和维护两者的经验来看:C语言中的可怕设计很难理解,分解和重构为可用的东西。
C ++中的可怕设计会变得更加糟糕,因为随机的抽象层使您的大脑在代码库中四处寻找,试图找出在哪种情况下将执行哪些代码。
如果我必须与那些不会产生出色设计的工程师一起工作,我宁愿选择前者而不是后者。
我看不到除了个人不喜欢的任何其他原因,即使是对嵌入式系统和类似事物进行编程也是如此。在C ++中,您仅为使用的功能支付开销。在某些特定情况下,您可能会使用C ++的C子集,而C ++开销对您来说太高了。这就是说,我认为某些C程序员高估了某些C ++构造的开销。让我列出一些例子:
一个正当的理由是当您在一个没有像样的C ++编译器的平台上进行编程时(根本没有C ++编译器,或者存在一个编译器,但是实现不当,并对某些C ++功能造成不必要的高开销)。
C ++的学习曲线更长。C只有很少的构造您需要了解,然后就可以开始编写功能强大的软件了。在C ++中,您需要学习C的基础知识,然后是OO和通用编程,异常等。而且一段时间之后,您可能会了解大多数功能,并且可能会使用它们,但是您仍然不知道编译器将如何使用它们。翻译它们,他们有没有隐式的开销。这需要很多时间和精力。
对于专业项目,这种说法可能不重要,因为您可以雇用已经非常了解C ++的人员。但是在仍然使用widley的C的开源项目中,人们选择了他们喜欢的语言并且能够使用。考虑到并不是每个OS程序员都是专业的程序员。
我想跟进丹·奥尔森的回答。我相信人们会担心C ++潜在的危险和适得其反的功能,这是合理的。但是,与Dan所说的不同,我认为仅仅确定一种编码标准并不是有效的,原因有两个:
我认为这里的第二个原因比第一个原因重要得多,因为确定编码标准很容易成为政治问题,以后可能会进行修订。考虑以下简化情况:
(根据经验,该标准未在步骤3中进行修订的替代方案太不可能考虑了,无论如何也不会更好。)
尽管几年前我曾经使用C ++进行几乎所有事情,但我开始强烈感觉到C在需要由C或C ++处理的低级任务中更可取,而其他所有事情都应该由其他方式完成语言完全。(唯一可能的例外是某些特定的高性能问题域,wrt。Blitz ++)
我从未见过有说服力的关于在C ++上使用C的论据。我认为大多数人通常会合理地担心C ++提供的某些功能。但这并不能说服我,因为人们可以通过编码标准来强制是否使用某些功能。即使在C语言中,您也要避免很多事情。完全放弃C ++本质上是说它没有C带来的明显好处,而C不会帮助人们编写更好的代码,我认为这是相当无知的观点。
此外,人们似乎总是提出不存在C ++编译器的平台的情况。当然在这里C是合适的,但我认为这些天很难找到这样的平台。
我还没有提到的一点是最重要的:
我每天使用的大多数库都是带有Python,Ruby,Perl,Java等绑定的C库。据我所知,用19种不同的语言绑定包装C库要容易得多。包装C ++库。
例如,我学到了开罗曾经,从那以后已经用3或4种不同的语言来使用它了。大赢了!我宁愿写一个将来可以再次使用的程序,而写一个可以很容易地被其他编程语言采用的程序就是一个极端的例子。
我知道可以绑定C ++库,但AFAICT并不相同。我已经在其他语言中使用过Qt(v3和v4),但使用起来却不太好:他们感觉就像用某种其他语言编写C ++,而不是像本机库一样。(您必须将C ++方法信号作为字符串传递!)
如果您要编写一次使用的函数,或者您认为全世界都是C ++,那么C ++可能是一种更好的语言。如果您从一开始就设计用于语言可移植性,那么C似乎是一种更简单的语言。
Windows内核开发不支持c ++(非常遗憾)。
您可以在此处阅读有关Linus Torvalds为什么偏爱C的有趣言论。
我可以想到几个原因。
可能没有令人满意的C ++编译器。C ++是一门更大的语言,我已经在无法处理现代C ++的系统上运行了C编译器。
发问者或与他或她合作的人可能熟悉C,但不熟悉C ++。
该项目可能在C中。尽管可以向C中添加一些C ++功能,但很容易导致混乱。我建议选择一种或另一种语言(在可行的情况下通常使用C ++)。
发问者可能对C ++的学习曲线不了解。(正确使用时,它比C容易。我见过的大多数入门书籍都不正确使用它。)
请记住,C和C ++是两种不同的语言,并且随着时间的流逝越来越多。同时进行两者编码是一个坏主意,并且使用类似C ++的C ++子集会错过C ++的大多数优点。
我认为C更可移植。大约5年前,我做了一些工作,将代码移植到许多版本的unix(AIX,Irix,HPUX,Linux)上。C代码很容易移植,但是在移植某些C ++代码时遇到了各种问题。也许这只是不成熟的开发环境,但是出于这个原因,我宁愿使用C而不是C ++。
C是一种简单的语言,而C ++不是。对于许多人来说,C ++太复杂而无法完全掌握,请参阅http://en.wikipedia.org/wiki/C%2B%2B#Criticism。
由于复杂性,不同的程序员通常只掌握语言的不同子集。这使阅读别人的代码很痛苦。
语言的复杂性,陷阱会增加过多的干扰,有时会损害生产力。我不去专注于工作本身,而是经常发现自己与语言本身作斗争。Java / python是更具生产力的替代方案。
通常,调试损坏的C代码比调试损坏的C ++代码要简单得多。
与Java / C#不同,C ++标准库在C标准库的范围之外几乎没有实现。
诸如Linus Torvalds(Linux)和Richard Stallman(Emacs)等一些著名的程序员不喜欢C ++。
我可以想到三个原因。一个原因是,由于C二进制文件的大小较小,并且C编译器在任何系统上的可用性更高,因此C更适合嵌入式系统。第二个是可移植性:C是一种较小的语言,并且ANSI C代码可以在任何地方编译。打破C ++的可移植性更容易。最后一个是语言本身。C ++较难,并且绝对是设计不良的语言。Torvalds抓地力报告于上方。您可能还需要查看C ++常见问题解答(http://yosefk.com/c++fqa/)。
可移植性可能是一个问题。与Gordon Carpenter-Thomp的答案不同,我建议它是在不同的linux / unix版本上支持不同版本的libstdc ++的运行时支持。请参阅此链接以对此进行良好的讨论。摘录:
C ++应用程序的不同部分使用的运行时支持代码需要兼容。如果程序的某一部分需要dynamic_cast或捕获另一部分提供的对象,则这两部分都必须在某些实现细节上达成共识:如何查找vtable,如何展开堆栈,等等。
对于C ++和其他一些具有类似功能的GCC支持的语言,此类详细信息由C ++ ABI指定。每当GCC使用的ABI发生更改时,您最终都会遇到由不同GCC版本产生的不兼容库。对于普通C来说也是如此,但是C ABI更为简单,而且已经存在了很长的时间,因此它相当稳定。