在听StackOverflow播客的时候,经常有人说“真正的程序员”是用C语言编写的,而C语言的速度要快得多,因为它“接近机器”。把前面的断言留到另一篇文章,C有什么特别之处,使它比其他语言更快?或者换句话说:什么能阻止其他语言编译成二进制代码,使其运行速度与C语言一样快?


当前回答

我还没有看到它,所以我要说:C往往更快,因为几乎所有其他东西都是用C写的。

Java是建立在C上的,Python是建立在C上的(或者Java,或者。net等等),Perl是等等。操作系统是用C写的,虚拟机是用C写的,编译器是用C写的,解释器是用C写的,有些东西仍然是用汇编语言写的,这往往更快。越来越多的东西是用别的东西写的,而这些东西本身就是用C写的。

您用其他语言(不是Assembly)编写的每个语句通常都在下面实现为C中的几个语句,这些语句被编译为本机机器代码。由于其他语言的存在往往是为了获得比C更高的抽象级别,因此C中所需的那些额外语句往往侧重于增加安全性、增加复杂性和提供错误处理。这些通常都是好事,但它们是有代价的,那就是速度和规模。

就我个人而言,我已经用几十种语言写过了,涵盖了大部分可用的范围,我个人也一直在寻找你暗示的魔法:

我怎样才能鱼与熊掌兼得呢?我如何在我最喜欢的语言中玩高级抽象,然后为了速度而降至C语言的细节?

经过几年的研究,我的答案是Python(在C上)。你可能想看看它。顺便说一下,您也可以从Python下拉到Assembly(从一个特殊的库中获得一些小小的帮助)。

另一方面,任何语言都可能编写出糟糕的代码。因此,C(或汇编)代码不会自动更快。同样,一些优化技巧可以使部分高级语言代码的性能水平接近原始c语言的性能水平。但是,对于大多数应用程序来说,程序的大部分时间都在等待人员或硬件,因此两者之间的差异实际上并不重要。

享受。

其他回答

我还没有看到它,所以我要说:C往往更快,因为几乎所有其他东西都是用C写的。

Java是建立在C上的,Python是建立在C上的(或者Java,或者。net等等),Perl是等等。操作系统是用C写的,虚拟机是用C写的,编译器是用C写的,解释器是用C写的,有些东西仍然是用汇编语言写的,这往往更快。越来越多的东西是用别的东西写的,而这些东西本身就是用C写的。

您用其他语言(不是Assembly)编写的每个语句通常都在下面实现为C中的几个语句,这些语句被编译为本机机器代码。由于其他语言的存在往往是为了获得比C更高的抽象级别,因此C中所需的那些额外语句往往侧重于增加安全性、增加复杂性和提供错误处理。这些通常都是好事,但它们是有代价的,那就是速度和规模。

就我个人而言,我已经用几十种语言写过了,涵盖了大部分可用的范围,我个人也一直在寻找你暗示的魔法:

我怎样才能鱼与熊掌兼得呢?我如何在我最喜欢的语言中玩高级抽象,然后为了速度而降至C语言的细节?

经过几年的研究,我的答案是Python(在C上)。你可能想看看它。顺便说一下,您也可以从Python下拉到Assembly(从一个特殊的库中获得一些小小的帮助)。

另一方面,任何语言都可能编写出糟糕的代码。因此,C(或汇编)代码不会自动更快。同样,一些优化技巧可以使部分高级语言代码的性能水平接近原始c语言的性能水平。但是,对于大多数应用程序来说,程序的大部分时间都在等待人员或硬件,因此两者之间的差异实际上并不重要。

享受。

C的设计者们已经做出了取舍。也就是说,他们决定把速度放在安全之上。C不会

检查数组下标边界 检查未初始化的变量值 检查内存泄漏 检查空指针解引用

当你索引到一个数组时,在Java中,它接受虚拟机中的一些方法调用,绑定检查和其他健全检查。这是有效的,绝对没问题,因为它在应有的地方增加了安全性。但是在C语言中,即使是非常微不足道的东西也不会被放在安全的地方。例如,C不要求memcpy检查要复制的区域是否重叠。它并不是一种用于编写大型商业应用程序的语言。

但是这些设计决策并不是C语言中的bug。它们是被设计出来的,因为它允许编译器和库编写者从计算机中获得每一点性能。下面是C语言的精神——C语言的基本原理文档是这样解释的:

C code can be non-portable. Although it strove to give programmers the opportunity to write truly portable programs, the Committee did not want to force programmers into writing portably, to preclude the use of C as a ``high-level assembler'': the ability to write machine-specific code is one of the strengths of C. Keep the spirit of C. The Committee kept as a major goal to preserve the traditional spirit of C. There are many facets of the spirit of C, but the essence is a community sentiment of the underlying principles upon which the C language is based. Some of the facets of the spirit of C can be summarized in phrases like Trust the programmer. Don't prevent the programmer from doing what needs to be done. Keep the language small and simple. Provide only one way to do an operation. Make it fast, even if it is not guaranteed to be portable. The last proverb needs a little explanation. The potential for efficient code generation is one of the most important strengths of C. To help ensure that no code explosion occurs for what appears to be a very simple operation, many operations are defined to be how the target machine's hardware does it rather than by a general abstract rule. An example of this willingness to live with what the machine does can be seen in the rules that govern the widening of char objects for use in expressions: whether the values of char objects widen to signed or unsigned quantities typically depends on which byte operation is more efficient on the target machine.

在过去,只有两种类型的语言:编译型和解释型。

编译语言利用“编译器”读取语言语法并将其转换为相同的汇编语言代码,这可以直接在CPU上进行。解释型语言使用了几种不同的方案,但从本质上讲,语言语法被转换成一种中间形式,然后在“解释器”(用于执行代码的环境)中运行。

因此,在某种意义上,在代码和机器之间存在另一个“层”——解释器。而且,在计算机中,越多就意味着使用更多的资源。翻译速度较慢,因为他们必须执行更多的操作。

More recently, we've seen more hybrid languages like Java, that employ both a compiler and an interpreter to make them work. It's complicated, but a JVM is faster, more sophisticated and way more optimized than the old interpreters, so it stands a much better change of performing (over time) closer to just straight compiled code. Of course, the newer compilers also have more fancy optimizing tricks so they tend to generate way better code than they used to as well. But most optimizations, most often (although not always) make some type of trade-off such that they are not always faster in all circumstances. Like everything else, nothing comes for free, so the optimizers must get their boast from somewhere (although often times it using compile-time CPU to save runtime CPU).

Getting back to C, it is a simple language, that can be compiled into fairly optimized assembly and then run directly on the target machine. In C, if you increment an integer, it's more than likely that it is only one assembler step in the CPU, in Java however, it could end up being a lot more than that (and could include a bit of garbage collection as well :-) C offers you an abstraction that is way closer to the machine (assembler is the closest), but you end up having to do way more work to get it going and it is not as protected, easy to use or error friendly. Most other languages give you a higher abstraction and take care of more of the underlying details for you, but in exchange for their advanced functionality they require more resources to run. As you generalize some solutions, you have to handle a broader range of computing, which often requires more resources.

保罗。

C语言并不总是更快。

C语言比现代Fortran语言慢。

在某些方面,C通常比Java慢。(特别是在JIT编译器对您的代码进行了测试之后)

C允许发生指针混叠,这意味着一些好的优化是不可能的。特别是当您有多个执行单元时,这将导致数据获取停滞。噢。

指针算术工作的假设确实会导致某些CPU系列(特别是PIC !)它曾经在x86上很差劲。

基本上,当你得到一个矢量单元,或者一个并行编译器,C语言很糟糕,而现代的Fortran运行得更快。

C程序员的一些技巧,比如thking(动态修改可执行文件)会导致CPU预取暂停。

明白我的意思了吗?

而我们的好朋友x86执行的指令集,如今与实际的CPU架构关系不大。影子寄存器,负载存储优化器,都在CPU中。所以C离虚拟金属很近。真正的金属,英特尔不会让你看到。(从历史上看,VLIW CPU有点破产,所以,也许这并不是那么糟糕。)

如果你在高性能DSP上用C编程(可能是TI DSP ?),编译器必须做一些棘手的事情,在多个并行执行单元之间展开C。因此,在这种情况下,C语言并不接近金属,但它接近编译器,它将进行整个程序优化。奇怪。

最后,一些cpu (www.ajile.com)在硬件中运行Java字节码。C将在该CPU上使用一个PITA。

里面有很多问题——大部分是我没有资格回答的问题。但对于最后一个:

有什么能阻止其他语言编译成运行速度和C一样快的二进制呢?

一句话,抽象。

C语言只比机器语言高出一到两个抽象层次。Java和. net语言距离汇编程序至少有3个抽象级别。Python和Ruby我不太确定。

通常,程序员的玩具越多(复杂的数据类型等),你离机器语言的距离就越远,需要做的翻译就越多。

我在这里和那里都偏离了,但这是基本的要点。

更新-------这篇文章有一些很好的评论,有更多的细节。