在听StackOverflow播客的时候,经常有人说“真正的程序员”是用C语言编写的,而C语言的速度要快得多,因为它“接近机器”。把前面的断言留到另一篇文章,C有什么特别之处,使它比其他语言更快?或者换句话说:什么能阻止其他语言编译成二进制代码,使其运行速度与C语言一样快?
当前回答
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一样快?
没什么。像Java或。net语言这样的现代语言更多地面向程序员的生产力,而不是性能。现在硬件很便宜。此外,编译到中间表示提供了很多好处,如安全性,可移植性等。net CLR可以利用不同的硬件-例如,你不需要手动优化/重新编译程序来使用SSE指令集。
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.
原因有很多,包括:
它被编译成汇编语言。 它是静态类型的。 没有垃圾回收。 没有异常机制。 编译器优化 C语言的哲学之一是保持简单并保持向后兼容性,而不是添加更多的特性。
如果你花了一个月的时间用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程序员必须对每几行代码做出这类低级决策。它加起来就是一个手工制作、手工优化的可执行文件。
The fastest running code would be carefully hand crafted machine code. Assembler will be almost as good. Both are very low level and it takes a lot of writing code to do things. C is a little above assembler. You still have the ability to control things at a very low level in the actual machine, but there is enough abstraction make writing it faster and easier then assembler. Other languages such as C# and JAVA are even more abstract. While Assembler and machine code are called low level languages, C# and JAVA (and many others) are called high level languages. C is sometimes called a middle level language.