Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么C这么快,为什么不是';其他语言的速度是快还是快?_C_Performance - Fatal编程技术网

为什么C这么快,为什么不是';其他语言的速度是快还是快?

为什么C这么快,为什么不是';其他语言的速度是快还是快?,c,performance,C,Performance,在收听StackOverflow播客时,jab不断提到“真正的程序员”是用C编写的,而C之所以快得多是因为它“离机器很近”。把前面的断言留给另一篇文章,C有什么特别之处使它比其他语言更快?或者换一种方式:什么能阻止其他语言编译成二进制,而二进制的运行速度和C一样快 什么能阻止其他语言 能够编译成二进制 它的运行速度和C一样快 没什么。像Java或.NET语言这样的现代语言更注重程序员的生产力,而不是性能。现在硬件很便宜。此外,编译到中间表示还带来了很多好处,如安全性、可移植性等。NET CLR可

在收听StackOverflow播客时,jab不断提到“真正的程序员”是用C编写的,而C之所以快得多是因为它“离机器很近”。把前面的断言留给另一篇文章,C有什么特别之处使它比其他语言更快?或者换一种方式:什么能阻止其他语言编译成二进制,而二进制的运行速度和C一样快

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


没什么。像Java或.NET语言这样的现代语言更注重程序员的生产力,而不是性能。现在硬件很便宜。此外,编译到中间表示还带来了很多好处,如安全性、可移植性等。NET CLR可以利用不同的硬件—例如,您不需要手动优化/重新编译程序来使用SSE指令集。

如果您花一个月的时间在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;
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 */
   }
}
函数RemoveAllAFromB(a,b:string):string;
变量
前后:字符串;
开始
结果:=b;
如果0<位置(a,b),则开始
前:=副本(b,1,位置(a,b)-长度(a));
之后:=副本(b,位置(a,b)+长度(a),长度(b));
结果:=之前+之后;
结果:=RemoveAllAFromB(a,结果)//递归的
结束;
结束;
我用C写下这个:

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;
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 */
   }
}
char*s1,*s2,*result;/*原始字符串和结果字符串*/
int len1,len2;/*弦的长度*/
对于(i=0;i
但是在C版本中有多少优化?我们做了很多关于实现的决定,我在Delphi版本中没有考虑这些。字符串是如何实现的?在德尔菲我看不到。在C语言中,我决定它将是一个指向ASCII整数数组的指针,我们称之为字符。在C语言中,我们一次测试一个字符是否存在。在Delphi中,我使用Pos


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

在大多数情况下,每个C指令都对应于极少数汇编指令。您实际上是在编写更高级的机器代码,因此您可以控制处理器所做的几乎所有事情。许多其他编译语言,如C++,有许多简单的指令,它们可以比你想象的多(虚拟函数、复制构造函数等等)。像Java或Ruby这样的解释语言还有另外一层你从未见过的指令——虚拟机或解释器。

与其说是语言,不如说是工具和库。C语言的可用库和编译器比新语言的旧得多。你可能认为这会让他们慢下来,但事实恰恰相反


这些库是在处理能力和内存都很高的时候编写的。他们必须写得非常有效率才能工作。C编译器的开发人员也花了很长时间为不同的处理器进行各种巧妙的优化。C语言的成熟和广泛采用使得它比同龄的其他语言具有显著的优势。它还使C在速度上比新工具更具优势,因为新工具不像C那样强调原始性能。

其中有很多问题,大多数问题我没有资格回答。但对于最后一个:

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

一句话,抽象

C与机器语言只有一到两个抽象层次。Java和.Net语言离汇编程序至少有3个抽象层次。我对Python和Ruby没有把握

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

我四处奔波,但这是基本要点


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

C设计人员做了一个折衷。也就是说,他们决定把速度置于安全之上。C不会的

  • 检查数组索引边界
  • 检查未初始化的变量值
  • 检查内存泄漏
  • 检查空指针取消引用
在Java中,当索引到数组中时,它会在虚拟机中进行一些方法调用、绑定检查和其他健全性检查。这是有效的,绝对没有问题,因为它增加了应有的安全性。但在C语言中,即使是非常琐碎的东西也不能放在安全的地方。例如,C不需要memcpy来检查要复制的区域是否重叠。它不是设计为一种编程大型商业应用程序的语言

但这些设计都是错误的
// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
// 
if (createParams == null) {
    createParams = new CreateParams(); 
}