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


当前回答

c语言并没有什么特别之处,这也是它速度快的原因之一。

新语言支持垃圾收集、动态类型和其他功能,使程序员更容易编写程序。

问题在于,会有额外的处理开销,这会降低应用程序的性能。C语言没有这些,这意味着没有开销,但这意味着程序员需要能够分配内存并释放它们以防止内存泄漏,并且必须处理变量的静态类型。

也就是说,许多语言和平台,如Java(其Java虚拟机)和。net(其公共语言运行时),多年来通过即时编译(从字节码生成本机机器代码以实现更高性能)等技术改进了性能。

其他回答

不要轻信别人的话,看看在代码的任何性能关键部分,C语言和你选择的语言的反汇编。我认为你可以在Visual Studio运行时的反汇编窗口中看到已分解的. net。如果Java使用windbg有点棘手,应该是可能的,尽管如果你用。net来做,许多问题将是相同的。

如果没有必要的话,我不喜欢用C来编写,但我认为,这些回答中吹捧除C之外其他语言的速度的许多主张可以放在一边,只需用C和您选择的高级语言分解相同的例程,特别是如果涉及大量数据(这在性能关键型应用程序中很常见)。Fortran在其专业领域可能是个例外,不知道。它比C高吗?

第一次比较JITed代码和本地代码时,我解决了。net代码是否能与C代码运行得相当的所有问题。额外的抽象层次和所有的安全检查都带来了巨大的成本。同样的成本可能也适用于Java,但不要相信我的话,在性能至关重要的地方尝试一下。(有没有人足够了解JITed Java来在内存中找到一个编译过的过程?这当然是可能的)

我在链接上找到了一个关于为什么有些语言更快,有些更慢的答案,我希望这将更清楚为什么C或c++比其他语言更快,还有一些其他语言也比C更快,但我们不能使用所有的语言。一些解释-

Fortran仍然重要的一个重要原因是它的速度快:用Fortran编写的数字处理例程往往比用大多数其他语言编写的等效例程要快。在这个领域与Fortran竞争的语言是C和c++,因为它们在性能上具有竞争力。

这就提出了一个问题:为什么?是什么让c++和Fortran速度如此之快?为什么它们比其他流行语言(如Java或Python)性能更好?

解释与编译 根据编程语言所鼓励的编程风格和所提供的特性,有许多方法可以对编程语言进行分类和定义。在性能方面,最大的区别是解释语言和编译语言之间的区别。

划分并不难;而是有一个光谱。在一端,我们有传统的编译语言,包括Fortran、C和c++。在这些语言中,有一个独立的编译阶段,将程序的源代码转换为处理器可以使用的可执行形式。

这个编译过程有几个步骤。对源代码进行分析和解析。基本的编码错误,如错字和拼写错误,此时可以检测到。解析后的代码用于生成内存中的表示,该表示也可用于检测错误——这一次是语义错误,例如调用不存在的函数,或者试图对文本字符串执行算术操作。

然后,这个内存中表示形式用于驱动代码生成器,即生成可执行代码的部分。代码优化,以提高所生成代码的性能,在此过程中的不同时间执行:可以在代码表示上执行高级优化,而在代码生成器的输出上使用低级优化。

实际执行代码发生在后面。整个编译过程只是用来创建可以执行的内容。

在另一端,我们有口译员。解释器将包括一个类似于编译器的解析阶段,但这随后用于驱动直接执行,程序立即运行。

最简单的解释器包含与该语言支持的各种特性相对应的可执行代码,因此它将具有用于添加数字、连接字符串以及给定语言所具有的任何其他功能的函数。当它解析代码时,它将查找相应的函数并执行它。在程序中创建的变量将保存在某种将其名称映射到其数据的查找表中。

解释器风格的最极端的例子是类似批处理文件或shell脚本的东西。在这些语言中,可执行代码通常甚至不内置在解释器本身中,而是单独的独立程序。

So why does this make a difference to performance? In general, each layer of indirection reduces performance. For example, the fastest way to add two numbers is to have both of those numbers in registers in the processor, and to use the processor's add instruction. That's what compiled programs can do; they can put variables into registers and take advantage of processor instructions. But in interpreted programs, that same addition might require two lookups in a table of variables to fetch the values to add, then calling a function to perform the addition. That function may very well use the same processor instruction as the compiled program uses to perform the actual addition, but all the extra work before the instruction can actually be used makes things slower.

如果你想知道更多,请查看来源

For the most part, every C instruction corresponds to a very few assembler instructions. You are essentially writing higher level machine code, so you have control over almost everything the processor does. Many other compiled languages, such as C++, have a lot of simple looking instructions that can turn into much more code than you think it does (virtual functions, copy constructors, etc..) And interpreted languages like Java or Ruby have another layer of instructions that you never see - the Virtual Machine or Interpreter.

如果你花了一个月的时间用C语言构建的程序只需要0.05秒,而我花了一天的时间用Java写同样的程序,只需要0.10秒,那么C语言真的更快吗?

但是回答你的问题,编写良好的C代码通常会比其他语言编写的代码运行得更快,因为编写良好的C代码的一部分包括在接近机器的级别上进行手动优化。

尽管编译器确实非常聪明,但它们还不能创造性地提出与手工按摩算法竞争的代码(假设“手”属于一个优秀的C程序员)。

编辑:

很多评论都是这样的:“我用C语言编写,我不考虑优化。”

举个具体的例子:

在Delphi中我可以这样写:

function RemoveAllAFromB(a, b: string): string;
var
  before, after :string;
begin
  Result := b;
  if 0 < Pos(a,b) then begin
    before := Copy(b,1,Pos(a,b)-Length(a));
    after := Copy(b,Pos(a,b)+Length(a),Length(b));
    Result := before + after;
    Result := RemoveAllAFromB(a,Result);  //recursive
  end;
end;

用C语言写:

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
   for (j = 0; j < len2; j++) {
     if (s1[i] == s2[j]) {
       break;
     }
   }
   if (j == len2) {  /* s1[i] is not found in s2 */
     *result = s1[i]; 
     result++; /* assuming your result array is long enough */
   }
}

但是C版本中有多少优化呢?我们在实现方面做了很多我在Delphi版本中没有考虑到的决定。字符串是如何实现的?在特尔斐我看不出来。在C语言中,我已经决定它将是一个指向ASCII整数数组的指针,我们称之为字符。在C语言中,我们每次测试一个字符的存在性。在Delphi中,我使用Pos。

这只是一个小例子。在一个大型程序中,C程序员必须对每几行代码做出这类低级决策。它加起来就是一个手工制作、手工优化的可执行文件。

C语言速度很快,因为它是原生编译的低级语言。但是C不是最快的。递归斐波那契基准测试表明Rust、Crystal和Nim可以更快。