为什么人为地限制你的代码到C?

这是由一个答案,我给了一个当前问题 ,询问有关C的generics库 – 提问者明确指出,他们不想使用C ++。 我对他和其他坚持使用C的人的问题是,为什么他们这样做的时候:

  • C ++提供了他们所要求的特定function
  • 他们的C编译器几乎肯定是一个C ++编译器,所以不存在软件成本问题
  • C ++和C一样可移植
  • C ++代码可以和C一样高效(或者更多,或者更less)

请注意:这并不是为了争辩 – 我真的对select语言的动机感兴趣。

编辑:有人build议,这是重复的,但我不认为这是。 为了澄清,我感兴趣的是为什么人们限制自己的C子集。 例如,我提到的post中的提问者可能保留了他所有的旧C代码,只是使用C ++generics容器作为“更好的数组” – 我感兴趣的是为什么人们对此非常抵触? 我不知道为什么你应该或不应该学习C或C ++。

Peter Kirkham的post对我来说是最丰富的,特别是关于我没有考虑过的C99问题,所以我已经接受了。 感谢所有参与其他人。

这是由一个答案,我给了一个当前问题,询问有关C的generics库 – 提问者明确指出,他们不想使用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风格的types,它可以用C编译,但是可以被大多数C ++编码标准避开)。

它们不是相同的语言,如果你有一个现有的C项目,你不想用一种不同的语言重写它只是为了使用一个库。 你更愿意使用你可以用你正在工作的语言接口的库。

把我正在工作的项目中的第一个C文件,这是如果你只是交换gcc std=c99 for 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行错误,其中四个是无效转换,但主要是针对C99中存在的function,而不是C ++中的function。

这不像我使用这些function的乐趣。 将其转移到不同的语言将需要大量的工作。

所以这个build议显然是错误的

[C] C编译器几乎可以肯定是一个C ++编译器,所以不存在软件成本问题

将现有的C代码移植到C ++的程序子集通常会带来巨大的成本影响。

因此,build议“使用C ++ std :: queue类”作为在C中查找队列的库实现的问题的答案,而不是build议使用“使用目标C”“使用JNI调用Java java.util.Queue类”“调用CPython库” – Objective C实际上是C(包括C99)的超集,而Java和CPython库都可以直接从C调用,而无需将不相关的代码移植到C ++语言中。

当然,您可以为C ++库提供一个Cfaçade,但是一旦您这样做,C ++与Java或Python没有区别。

我意识到这既不是一个专业,也不是一个特别好的答案,但对我来说,只是因为我非常喜欢C. C是小而简单的,我可以把整个语言放在我的大脑中,C ++对我来说似乎是一个巨大的广泛的混乱与各种各样的层我难过grokking。 由于这个原因,我发现每当我写C ++的时候,我最终花费了更多的时间去debugging,并且比我编码C的时候更猛烈。我再次意识到,这很大程度上是由于我自己的“无知”造成的。

如果我select,我会写所有的高层次的东西,比如在python(或者C#)中的接口和数据库交互,以及所有必须在C中快速的东西。对我来说,这是我所有世界中最好的东西。 用C ++编写所有东西感觉就像是在所有世界中最糟糕的一样。

编辑:我想补充一点,我认为C几个C ++function是一个坏主意,如果你要成为几个人在一个项目上工作,或者如果可维护性是优先考虑的。 关于什么是“less数”,哪些位应该用C来完成,以及C ++中的哪些位最终导致非常精神分裂的代码库,将会有分歧。

C ++在一些真实世界的环境中是不被支持的,比如低级embedded式系统。 有一个很好的理由:对于这样的事情,C很容易,所以为什么要用更大的东西呢?

我讨厌用C ++编程。

有几个原因可能是:

  • 缺乏支持 – 并非每个C编译器都是C ++编译器。 并非所有编译器都特别符合标准,即使他们声称支持C ++。 而一些C ++编译器会产生无望的膨胀和低效的代码。 一些编译器有标准库的可怕实现。 内核模式开发通常不可能使用C ++标准库,以及一些语言特性。 如果您坚持语言的核心,您仍然可以编写C ++代码,但是切换到C可能会更简单
  • 熟悉。 C ++是一种复杂的语言。 教C的人比C ++更容易,找一个好的C程序员比一个好的C ++程序员容易。 (这里的关键词“很好”,有很多C ++程序员,但是他们中的大多数没有正确的学习语言)
  • 学习曲线 – 如上所述,教导某人C ++是一项艰巨的任务。 如果你正在编写一个必须由其他人维护的应用程序,而这些应用程序可能不是C ++程序员,那么使用C编写应用程序会让你更容易掌握。

当我可以摆脱它的时候,我仍然更喜欢用C ++编写,总的来说,我认为它的好处大于弊。 但是我也可以看到在某些情况下使用C的理由。

关于embedded式编程,性能和东西有很多争论,我不买它们。 C ++在这些领域很容易与C进行比较。 然而:

就在最近在C ++中编程超过15年之后,我已经重新发现了我的C根。 我必须说,虽然在C ++中有很好的function使得生活更加简单,但也有一些陷阱和一种“永远存在”的做法。 你从来没有真正对你所做的解决scheme感到高兴。 (不要误解我的意思,这可能是一件好事,但大多不是)。

C ++给你无限的枪声。 这可以说是好的,但不知何故,你总是最终使用太多。 这意味着你用“好”和“漂亮”的抽象层次,通用性等来掩盖你的解决scheme。

我发现回到C的时候,实际上是再次有趣的编程。 花了这么多时间来模拟和思考如何最好地使用inheritance,我发现使用C编程实际上使我的源代码更小,更易读。 这当然取决于你的自律水平。 但是,对于直接转发的代码,实际上并不需要太多的抽象,这是非常容易的。

C有一个主要的优点,就是当你看一段代码的时候,你可以看到真正发生了什么(是的预处理器:用-E编译,然后你就可以看到它)。 当您查看一些C ++代码时,往往不是这样的。 在那里你有构造函数和析构函数,它们是基于范围隐含地调用的,或者是由于赋值的原因,你有运算符重载,即使没有被严重误用,也可能有令人吃惊的行为。 我承认我是一个控制怪胎,但是我得出这样的结论:对于想要编写可靠软件的软件开发人员来说这不是一个坏习惯。 我只是想有一个公平的机会说我的软件能够完成它应该做的事情,同时也不会在我肚子里有一种不好的感觉,因为我知道它里面还有很多的bug,当我看到导致它们的代码时,我甚至都没有注意到。

C ++也有模板。 我讨厌和爱他们,但如果有人说他或她完全理解他们,我就称他为骗子! 这包括编译器编写人员以及参与定义标准的人员(当您尝试读取标准时,这一点变得很明显)。 有这么多荒谬误导的angular落案件涉及到,当你写实际的代码时根本无法考虑它们。 我非常喜欢C ++模板。 你可以用他们做什么,真是太神奇了,但是他们同样可以导致最奇怪和最难find的错误。 而这些错误实际上是发生的,甚至很less发生。 阅读有关在C ++ ARM中解决模板问题的规则,几乎让我头脑发热。 而且,这让我感到浪费时间,不得不阅读几千个字符长的编译器错误消息,为此我需要10分钟或更长时间来理解编译器实际上对我的要求。 在典型的C ++(库)代码中,您还经常在头文件中发现大量代码,使得某些模板成为可能,这又使得即使在快速机器上编译/执行循环也非常缓慢,并且当您更改某些内容时需要重新编译大部分代码那里。

C ++也有const陷阱。 除了最琐碎的用例之外,你要么避免使用const,要么迟早不得不抛弃它,或者在它发展的时候重构大部分代码库,特别是当你要开发一个漂亮而灵活的OOdevise的时候。

C ++比C有更强的input,这很好,但是当我尝试编译C ++代码的时候,有时候我觉得自己正在喂一个Tamagotchi。 我通常从中得到的很大一部分警告和错误并不是我自己做的事情,但是只是编译器不喜欢我这样做,或者没有在这里添加一些额外的关键字,那里。

这些只是我不喜欢用C ++编写的软件的一些原因,我只是使用一些据称强大的外部库来编写软件。 当你与其他人一起编写代码时,真正的恐怖就开始了。 无论他们是非常聪明的C ++黑客还是天真的初学者,这几乎都不重要。 每个人都犯错误,但C ++使得故意难以find它们,甚至更难以发现它们。

使用C ++,你只是简单地丢失了,而没有经常使用debugging器,但我希望能够在我的脑海中validation我的代码的正确性,而不必依赖debugging器来find我的代码,这些代码是我永远不会想到的。 我实际上试图在我的脑海里运行我所有的代码,甚至在子程序等方面也尝试把它拥有的所有分支,并偶尔使用一个debugging器,只是为了看看它在我准备好的所有舒适的地方运行得多好。 编写和执行如此多的testing用例,所有代码path已经被用于所有组合的各种奇怪的input数据是根本不可能的。 所以你可能不知道C ++程序中的错误,但这并不意味着它们不在那里。 C ++项目越大越低,因此我相信即使它能够完美地运行我们手头的所有testing数据,也不会有很多未被发现的错误。 最后,我把这个垃圾丢了,重新开始一些其他的语言或其他语言的组合。

我可以继续,但是我想我现在已经清楚了我的观点。 所有这些让我在使用C ++编程的时候感觉没有任何效果,并且让我对自己的代码的正确性失去信心,这意味着我不再使用它了,而我仍然使用并依赖于C编写的超过20多年前。 也许这仅仅是因为我不是一个好的C ++程序员,或者在C和其他语言中可能相当出色,这使我能够认识到C ++的实际情况,而且我将永远无法完全理解它。

生命短暂…

在低级embedded式环境中,一些“软件工程师”将具有EE背景,并且几乎没有掌握C语言.C ++更加复杂,其中一些人害怕学习一门新的语言。 因此C被用作最低公分母。 (在你build议摆脱这些家伙之前,他们至less和那些不懂硬核模拟的CS大师一样重要。)

从inheritance和维护两者的经验来讲:在C中一个可怕的devise很难理解,放松,并重构成可用的东西。

C ++中的一个可怕的devise是随着抽象的抽象层发送你的脑子在代码库周围试图找出哪个代码将在哪种情况下执行的无情更糟糕的devise。

如果我必须和我认识的工程师合作不会产生出色的devise,我宁愿拥有前者而不是后者。

我没有看到任何个人不喜欢的理由,即使是编程embedded式系统和类似的东西。 在C ++中,您仅为您使用的function支付开销。 在C ++开销对您来说太高的特定情况下,您可以使用C ++的C子集。 这就是说,我认为一些C程序员高估了一些C ++构造的开销。 让我列举一些例子:

  • 类和成员函数与正常函数相比没有任何开销(除非使用虚函数,在这种情况下,与使用函数指针相比​​,没有开销)
  • 模板的开销很小(通常没有开销)

一个有效的原因是当你编写一个没有像样的C ++编译器的平台时(根本没有C ++编译器,或者编译器存在,但是实现不好,并且对于某些C ++特性施加了不必要的高开销)。

为什么限制英语口语? 也许你会成为塞尔维亚更有创造力的作家。

这是相同的论点,有明显的谬误。 如果您有任务,而且您的舒适工具可以有效地解决任务,那么您可能会使用舒适的工具。

C ++有更长的学习曲线。 C只有几个你需要知道的构造,然后你可以开始编写function强大的软件。 在C ++中,你需要学习C语言基础,然后是面向对象和generics编程,exception等。一段时间后,你可能知道大部分的function,你可能会使用它们,但是你仍然不知道编译器将如何翻译他们,他们有或没有隐含的开销。 这需要很多时间和精力。

对于一个专业项目来说,这个论点可能不算,因为你可以雇用已经很熟悉C ++的人。 但在开源项目中,C仍然是widley使用,人们select他们喜欢的语言,他们可以使用。 考虑到并不是每个OS程序员都是专业程序员。

我从来没有看到任何使用C ++,而我认为令人信服的论点。 我认为大多数人都害怕C ++提供的某些function,经常是合理的。 然而,这并不能说服我,因为可以通过编码标准强制执行某些function。 即使在C中,也有很多你想避免的。 完全抛弃C ++本质上是说它没有提供比C更实际的好处,有助于编写更好的代码,这是我认为很无知的一种观点。

另外,人们似乎总是提出没有C ++编译器的平台的情况。 当然C在这里是适当的,但是我觉得你现在很难find这样的平台。

我想跟进丹·奥尔森的回答。 我相信人们害怕C ++的潜在危险和反作用的特征,而且是合理的。 但是,与Dan所说的不同,我不认为简单地决定编码标准是有效的,原因有二:

  1. 编码标准可能难以严格执行
  2. 想出一个好的scheme可能非常困难。

我认为这里的第二个原因比第一个原因重要得多,因为决定编码标准很容易成为一个政治问题,稍后会进行修改。 考虑下面的简化情况:

  1. 你被允许使用stl容器,但不能在你自己的代码中使用模板。
  2. 人们开始抱怨说,如果他们被允许编写这个或那个模板类,他们会更有效率。
  3. 编码标准修改为允许的。
  4. 将一个斜率滑到一个过于复杂的编码标准,没有人遵循这个标准,并使用标准应该防止的那种危险代码,再加上围绕标准的过度官僚主义。

(在第三步中没有修改标准的替代scheme实际上不太可能考虑,反正也不会好得多。)

尽pipe几年前我曾经使用过C ++,但是我开始强烈地感觉到C在低级别任务中是可取的,这些低级任务需要由C或C ++来处理,而其他所有事情都应该在其他一些任务中完成语言完全。 (只有可能的例外是一些特定的高性能问题域,wrt。Blitz ++ )

我使用C,或者在编写库代码时至less导出一个C接口。

我不想要不明确的ABI麻烦。

有一点我还没有看到,我认为是最重要的:

我每天使用的大多数库都是C库,包含Python,Ruby,Perl,Java等的绑定。从我所看到的情况来看,使用19种不同的语言绑定来包装C库要容易得多。包装C ++库。

例如,我曾经学习过开罗 ,从那以后用过三,四种不同的语言。 大赢! 我宁愿写一个可以在将来再次使用的程序,编写一个可以很容易地被其他编程语言采用的程序就是一个极端的例子。

我知道可以绑定C ++库,但AFAICT是不一样的。 我在其他语言中使用过Qt(v3和v4),并且使用起来并不是很好:他们觉得像使用其他语言编写C ++,而不是使用本地库。 (您必须将C ++方法sigs作为string传递!)

如果你正在编写一个函数来使用一次,或者你认为所有的世界都是C ++,C ++可能是一个更好的语言。 如果从一开始就devise语言可移植性,C似乎是一种更简单的语言。

Windows内核开发不支持c + +(可悲)。

You can read an entertaining rant about why Linus Torvalds favours C here

Native code on a mac is objective-c. Native code on a PC is c (window.h) or c++ (mfc). Both of these environments will let you use c with little or no changes. When I want a library of code to be cross platform ansi c seems like a good choice.

I can think of several reasons.

There may not be a satisfactory C++ compiler. C++ is a much bigger language, and I've run C compilers on systems that would not be able to handle modern C++.

The questioner, or people he or she works with, may be familiar with C but not C++.

The project may be in C. While it's possible to add some C++ features to C, that can easily lead to an unmaintainable mess. I'd suggest picking one language or the other (usually C++, when practical).

The questioner may have an obsolete view of C++'s learning curve. (When approached correctly, it's easier than C's. Most introductory books I've seen don't approach it correctly.)

Remember that C and C++ are two different languages, and are getting more different over time. Coding in both at once is a bad idea, and using a C-like subset of C++ misses most of the advantages of C++.

If you work in an environment with two languages, you might use C for some performance critical low-level functions and a more functional/high level language like C#/Java for the business logic. If C++ code is usedfor these functions ,C-Wrappers are required for JNI/unmanaged code around and this makes things more complex than solely using C.

I use C++ with C programming for two reasons:

  • vector and string to get the array memory management away from me
  • strict type checking and casts to warn and/or catch allthe nuisances I would miss otherwise.

So it is C really borrowing a few c++ but using the c++ compiler as much as I can. As someone else says in the answers, I find now I am actually picking up more C++ this way and where C would be too involving, I use C++. Monitor/Lock using RAII is one of these I've used recently when dealing with multi-threaded programs and another similar construct to open/close files.

I think C is more portable. I did some work about 5 years ago porting code to many flavours of unix (AIX,Irix,HPUX,Linux). The C code was easy to port but we had various problems porting some of the C++ code across. Maybe it was just immature development environments but i would much rather use C over C++ for this reason…

  1. C is a simple language, C++ is not. For many people, C++ is simply too complicated to fully master, see http://en.wikipedia.org/wiki/C%2B%2B#Criticism .

  2. Because of the complexity, different programmers usually only master different subsets of the language. It makes reading other people's code painful.

  3. The complexity, pitfalls of the language add too much distraction, and sometimes hurt productivity. Instead of focus on the job itself, I often found myself fighting with the language itself. Java/python are more productive alternatives.

  4. Debugging a broken C code is usually much more straightforward than debugging a broken C++ code.

  5. Unlike Java/C#, the C++ standard library achieves little beyond the scope of the C standard library.

  6. Some famous programmers like Linus Torvalds (Linux) and Richard Stallman (Emacs) dislike C++.

Most programmers take it for granted that everyone considers quality a high priority. That's not always the case. If you're use to C, C++ might seem like it's doing too much for you behind the scenes. The strictness of type checking in C++ might also seem confining. Many people are willing to risk introducing the kinds of bugs that C++ can help prevent to avoid these "nuisances."

There are three reasons I can think of. One is that C is more suited for embedded systems, due to the small size of its binaries and the wider availability of C compilers on any system. The second is portability: C is a smaller language, and and ANSI C code will compile anywhere. It's easier to break portability in C++. The last one is the language itself. C++ is harder, and is most definitely a very poorly designed language. Torvalds gripes are reported above. You may also want to look at the C++ Frequently Questioned Answers ( http://yosefk.com/c++fqa/ ).

Portability may be an issue. Different to Gordon Carpenter-Thomp's answer, I would suggest that it's rather the runtime support of different versions of libstdc++ on different linux/unix versions. See this link for a good discussion about this. A little excerpt:

The runtime support code used by different parts of a C++ application needs to be compatible. If one part of the program needs to dynamic_cast or catch objects provided by another, both parts must agree on certain implementation details: how to find vtables, how to unwind the stack, and so on.

For C++ and a few other GCC-supported languages with similar features, such details are specified by a C++ ABI. Whenever the ABI used by GCC changes you'll end up with incompatible libraries produced by the different GCC versions. The same is true for plain C, but the C ABI is much simpler and has been around a lot longer so it's fairly stable.

I can follow many suggestions here in both directions. But in the end it comes down to a) comparable simple b) comparable complex.

I don't have an idea if someone has "invented" a sort of language complexity measurement.

On a scale from 0 – 10 I probably would rate C at 2 or 3 whereas C++ would be between 8-10. I'd argue C++ is one of the most complex languages but I do not know eg Ada, PL1 or the like, so maybe it's not that complex in comparison to some other language.

C++ inherits all complexity of C so it can not be below the complexity level of C.

I for my part would be much more comfortable using some scripting language and C. So in the end one has to answer the following question. "Is more always better?"

Most people seem to think that C and C++ are somehow related, but they are sadly mistaken. C++ is a completely different language than C.

In C++, you think in terms of objects and how they are related to each other. In C, you think in terms of APIs. It's like the difference between day and 17.

A poor analogy: if someone adds Chinese to English and calls it English++, you probably wouldn't feel comfortable to add a Chinese line to your latest love letter, because it's so much easier to express love in this part of English++.

The most useful thing I found in C is the lack of namespaces and overloads: function and symbol names are unique identifiers. To find the places where these symbols are used you can just grep through the source code files and search results will shows the locations.

It's essential when wiring in a new feature or component to an old and tangled system.

You cannot do this easily in C++, without a sophisticated call graph building tool.

The following are all reasons why it may be beneficial to limit a project to C:

  • faster compilation because the language is much simpler
  • requires less runtime support, making it more suitable low-level environments
  • much easier to interface with other languages
  • supports variable sized arrays on the stack
  • easier to read assembly code because there is no name mangling
  • allows code produced by different compilers to be easily combined since it is the de facto standard application binary interface