在收听StackOverflow播客时,jab不断出现“真正的程序员”用C语言编写,并且C语言更快,因为它“靠近机器”。将前一个断言留给另一个帖子,C的特殊之处在于它是否比其他语言更快?或者换一种方式:什么阻止其他语言能够编译成与C一样快的每一位运行的二进制文件?
答案 0 :(得分:191)
关于C没有太多特别之处。这就是它快速的原因之一。
支持garbage collection,dynamic typing和其他工具的新语言,使程序员更容易编写程序。
问题是,存在额外的处理开销,这将降低应用程序的性能。 C没有任何这些,这意味着没有开销,但这意味着程序员需要能够分配内存并释放它们以防止memory leaks,并且必须处理变量的静态类型。
也就是说,许多语言和平台,例如Java(使用其Java Virtual Machine)和.NET(及其公共语言运行时),多年来通过just-in-time compilation之类的问题提高了性能。来自字节码的本机机器代码,以实现更高的性能。
答案 1 :(得分:86)
C设计师已经做出了折衷。也就是说,他们决定将速度提高到安全之上。 C不会
当您索引到数组时,在Java中,它需要在虚拟机中进行一些方法调用,绑定检查和其他健全性检查。 是有效且绝对正常的,因为它增加了应有的安全性。但在C语言中,即使是非常琐碎的事情也不会安全。例如,C不需要memcpy来检查要复制的区域是否重叠。 不设计为编写大型业务应用程序的语言。
但是这些设计决策不是C语言中的错误。它们是设计的,因为它允许编译器和库编写者从计算机中获得所有性能。以下是C Rationale文档解释它的C精神:
C代码可以是不可移植的。虽然它努力为程序员提供编写真正可移植程序的机会,但委员会并不想强迫程序员编写程序,以排除使用C语言作为“高级汇编程序”:编写机器特定代码的能力是C的优势之一。
保持C的精神。委员会将保持C的传统精神作为一个主要目标.C的精神有许多方面,但其实质是社区的情感。 C语言所依据的基本原则。 C精神的一些方面可以用
这样的短语来概括
- 相信程序员。
- 不要阻止程序员做必须做的事情。
- 保持语言简洁。
- 只提供一种方法来进行操作。
- 即使不保证便携,也要快速。
最后一句谚语需要一点解释。高效代码生成的潜力是C最重要的优势之一。为了帮助确保看起来非常简单的操作不会发生代码爆炸,许多操作被定义为目标机器的硬件如何做而不是通过一般的抽象规则。在管理用于表达式的char对象的扩展的规则中可以看到这种意愿与机器一起工作的一个例子:char对象的值扩展到有符号或无符号量通常取决于哪个字节操作更多在目标机器上高效。
答案 2 :(得分:72)
如果你用一个月的时间在C中构建一个运行时间为0.05秒的东西,并且我花了一天时间在Java中编写相同的东西,并且它在0.10秒内运行,那么C真的更快吗?
但是要回答你的问题,编写良好的 C代码通常比其他语言中编写良好的代码运行得更快,因为写“C代码”的部分内容包括在附近进行手动优化机器水平。
尽管编译器确实非常聪明,但他们还没有能够创造性地提出与手动按摩算法竞争的代码(假设“手”属于好的 C程序员)。 / p>
修改强>
许多评论都是“我用C编写而我不考虑优化。”
但是举个具体的例子from this post:
在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版本中做了很多关于实现的决定。字符串是如何实现的?在Delphi中我没有看到它。在C中,我决定它将是一个指向ASCII整数数组的指针,我们将其称为chars。在C中,我们一次测试一个角色存在。在Delphi中,我使用Pos。
这只是一个小例子。在一个大型程序中,C程序员必须使用每几行代码进行这些类型的低级决策。它增加了手工制作,手工优化的可执行文件。
答案 3 :(得分:46)
我没有看到它,所以我会说: C往往更快,因为几乎所有其他内容都是用C 编写的。
Java是基于C构建的,Python是基于C(或Java,或.NET等)构建的,Perl是等等。操作系统是用C语言编写的,虚拟机是用C语言编写的,编译器是用C编写的在C中,解释器是用C语言编写的。有些东西仍然用汇编语言编写,后者往往更快。越来越多的东西被写在其他东西上,这本身就是用C语言编写的。
您使用其他语言(而不是Assembly)编写的每个语句通常在C下面作为几个语句实现,这些语句被编译为本机机器代码。由于为了获得比C更高的抽象级别而倾向于存在其他语言,因此C中所需的那些额外语句往往侧重于增加安全性,增加复杂性和提供错误处理。这些通常是好事,但它们的成本 ,其名称是速度和尺寸。
就我个人而言,我用几十种语言编写了大部分可用频谱,我个人已经找到了你暗示的魔力:
我怎样才能吃蛋糕呢?我怎样才能用我最喜欢的语言进行高级抽象,然后深入了解C的细节以获得速度?
经过几年的研究,我的答案是Python(在C上)。你可能想看一看。顺便说一句,您也可以从Python下载到Assembly(在特殊库的帮助下)。
另一方面,bad code can be written in any language。因此,C(或汇编)代码不会自动更快。同样,一些优化技巧可以使高级语言代码的部分接近原始C的性能级别。但是,对于大多数应用程序,您的程序大部分时间都在等待人员或硬件,所以差异真的没关系。
享受。
答案 4 :(得分:35)
那里有很多问题 - 大部分是我没有资格回答的问题。但对于最后一个:
什么阻止其他语言能够编译成与C一样快的每一位运行的二进制文件?
总之,抽象。
C只是远离机器语言的一个或两个抽象级别。 Java和.Net语言至少有3个抽象级别,远离汇编程序。我不确定Python和Ruby。
通常情况下,程序员玩具越多(复杂的数据类型等),您就越远离机器语言,必须完成更多的翻译工作。
我不在这里,但这是基本的要点。
更新 -------这篇文章有一些很好的评论,有更多细节。
答案 5 :(得分:30)
C的速度并不快,因为 C的成本模型是透明的。如果C程序很慢,那么它显然很慢:通过执行大量语句。与C中的操作成本相比,对对象(尤其是反射)或字符串的高级操作可能会产生不明显的成本。
通常编译为二进制文件的两种语言与标准ML(使用MLton编译器)和Objective Caml一样快。如果你查看benchmarks game,你会发现对于某些基准测试,比如二叉树,OCaml版本比C更快。(我没有找到任何MLton条目。)但是也不要拍摄枪支认真;正如它所说的那样,游戏结果通常反映了人们在调整代码方面付出了多少努力。
答案 6 :(得分:18)
C并不总是更快。
C比现代Fortran慢。
对某些事情来说,C通常比Java慢。 (特别是在JIT编译器完成了代码之后)C让指针别名发生,这意味着一些好的优化是不可能的。特别是当您有多个执行单元时,这会导致数据获取停顿。流。
假设指针算法确实能够在某些CPU系列上产生缓慢的性能(特别是PIC!)它过去常常在分段x86上吸掉大的。
基本上,当你得到一个向量单元或并行编译器时,C会发臭,现代Fortran会运行得更快。
C程序员的技巧就像thunking(动态修改可执行文件)导致CPU预取停顿。
你得到漂移?
我们的好朋友x86执行的指令集现在与实际的CPU架构几乎没有关系。影子寄存器,加载存储优化器,都在CPU中。所以C接近虚拟金属。真正的金属,英特尔不会让你看到。 (从历史上看,VLIW CPU有点像一个半身像,所以也许没有那么糟糕。)
如果您使用高性能DSP(可能是TI DSP?)在C上编程,编译器必须做一些棘手的事情来在多个并行执行单元中展开C.所以在这种情况下C不接近金属,但它接近编译器,这将完成整个程序。怪异。
最后,一些CPU(www.ajile.com)在硬件中运行Java字节码。 C将是PITA在该CPU上使用。
答案 7 :(得分:11)
什么是阻止其他语言 能够编译成二进制 它的运行速度和C一样快?
无。 Java或.NET等现代语言更多地依赖于程序员的生产力而不是性能。硬件现在很便宜。编译到中间表示也提供了许多奖励,例如安全性,可移植性等..NET CLR可以利用不同的硬件 - 例如,您不需要手动优化/重新编译程序以使用SSE指令集。
答案 8 :(得分:8)
主要因素是它是一种静态类型语言,并且编译为机器代码。此外,由于它是一种低级语言,它通常不会做任何你不告诉它的事情。
这些是我想到的其他一些因素。
大多数静态类型的语言都可以像C一样快或者快地编译,特别是如果他们可以假设C不能因为指针别名等原因而等。
答案 9 :(得分:8)
我猜你忘了汇编语言也是一种语言:)
但严重的是,只有当程序员知道他在做什么时,C程序才会更快。您可以轻松编写一个C程序,该程序的运行速度比使用其他语言执行相同工作的程序慢。
C更快的原因是因为它是以这种方式设计的。它可以让你做很多“低级”的东西,帮助编译器优化代码。或者,我们应该说,程序员负责优化代码。但它通常非常棘手且容易出错。
与其他语言一样,其他语言更多地关注程序员的工作效率。人们普遍认为程序员的时间比机器时间要贵得多(即使在过去)。因此,最大限度地减少程序员花在编写和调试程序上的时间而不是程序的运行时间是很有意义的。要做到这一点,你将牺牲一些你可以做的事情来使程序更快,因为许多事情是自动化的。
答案 10 :(得分:7)
C ++平均速度更快(因为它最初是C的超集,尽管存在一些差异)。但是,对于特定的基准测试,通常会有另一种语言更快。
https://benchmarksgame-team.pages.debian.net/benchmarksgame/
fannjuch-redux
在Scala中最快
n-body
和fasta
速度更快。
spectral-norm
最快。
reverse-complement
,mandelbrot
和pidigits
最快。
regex-dna
是JavaScript中最快的。
chameneou-redux
最快的是Java 7。
thread-ring
在Haskell中最快。
其余的基准测试在C或C ++中最快。
答案 11 :(得分:6)
我认为没有人提到C编译器比其他任何编译器都付出了更多的努力,可能除了Java之外。
由于许多原因,C语言极其优化 - 超过几乎任何其他语言。因此,如果将相同的努力量投入到其他语言编译器中,C可能仍会名列前茅。我认为至少有一种候选语言可以比C更好地优化,因此我们可以看到生成更快二进制文件的实现。我正在考虑数字火星D,因为创建者注意构建一种可能比C更好地优化的语言。可能还有其他语言具有这种可能性。但是我无法想象任何语言都会让编译器比最好的C编译器快几个百分点。我想爱错。
我认为真正的“低悬的果实”将是用于人类优化的语言。熟练的程序员可以使任何语言更快 - 但有时你必须做荒谬的事情或使用不自然的结构来实现这一点。虽然它总是需要付出努力,但是一个好的语言应该能够产生相对快速的代码,而不必过于专注于程序的编写方式。
同样重要的是(至少对我来说)最坏的情况代码往往很快。网上有许多“证明”,Java比C更快或更快,但这是基于樱桃挑选示例。我不是C的忠实粉丝,但我知道我用C写的任何东西都会运行良好。使用Java,它“可能”在15%的速度内运行,通常在25%以内,但在某些情况下可能会更糟。任何情况下,它的速度一样快或在几个百分之内,通常是由于大部分时间花在库代码上,无论如何都要进行大量优化。
答案 12 :(得分:5)
在大多数情况下,每个C指令都对应很少的汇编指令。您实际上是在编写更高级别的机器代码,因此您几乎可以控制处理器所做的一切。许多其他编译语言,如C ++,有很多简单易懂的指令,可以转化为比你想象的更多的代码(虚函数,复制构造函数等)。而像Java或Ruby这样的解释语言有另外一层您从未见过的说明 - 虚拟机或口译员。
答案 13 :(得分:5)
这些答案中的许多答案给出了为什么C更快或更快(一般情况下或在特定情况下)的正当理由。不可否认的是:
尽管如此,我认为还有其他一些事情,我认为,与其他许多因素相比,C与其他语言的比较性能更为显着。即:
其他语言通常可以更轻松地编写执行速度更慢的代码。通常,它甚至受到语言设计理念的鼓舞。推论:C程序员更有可能编写不执行不必要操作的代码。
例如,考虑一个简单的Windows程序,其中创建了一个主窗口。 C版本将填充WNDCLASS[EX]
结构,该结构将传递给RegisterClass[Ex]
,然后调用CreateWindow[Ex]
并进入消息循环。高度简化和缩写的代码如下:
WNDCLASS wc;
MSG msg;
wc.style = 0;
wc.lpfnWndProc = &WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWndCls";
RegisterClass(&wc);
CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
C#中的等效程序可能只是一行代码:
Application.Run(new Form());
这一行代码提供了近20行C代码所具有的所有功能,并添加了一些我们遗漏的内容,例如错误检查。更丰富,更丰富的库(与典型的C项目中使用的库相比)为我们做了很多工作,让我们有时间编写更多代码片段,这些代码片段看起来很短,但涉及到幕后的许多步骤。
但是,一个能够轻松快速地编写代码的丰富库并不是我的观点。当你开始检查当我们的小单行实际执行时实际发生了什么时,我的观点会更加明显。为了好玩,在Visual Studio 2008或更高版本中enable .NET source access,并进入上面的简单one-linef。你会遇到的一个有趣的小宝石是Control.CreateParams
的吸气器中的这条评论:
// 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();
}
十次。大约相当于WNDCLASSEX
结构中存储的内容和传递给CreateWindowEx
的内容之和的信息在存储于之前从Control
类中检索了十次一个WNDCLASSEX
结构,并传递给RegisterClassEx
和CreateWindowEx
。
总而言之,执行此基本任务所执行的指令数量在C#中比在C中多2-3个数量级。部分原因是由于使用了功能丰富的库,这是必然的与我们简单的C代码相比,它完全符合我们的需要,仅此而已。但部分原因在于,.NET框架的模块化,面向对象的特性使得自身可以通过程序方法避免大量重复执行。
我不是想选择C#或.NET框架。我也不是说模块化,泛化,库/语言功能,OOP等是坏事。我曾经在C中进行大部分开发,后来在C ++中进行,最近在C#中进行。同样,在C之前,我主要使用汇编。随着语言的每一步“更高”,我会在更短的时间内编写更好,更易维护,更强大的程序。但是,它们的执行速度往往会慢一点。
答案 14 :(得分:5)
这实际上是一种长期存在的谎言。虽然C程序通常更快,但情况并非总是如此,特别是如果C程序员不是很擅长它。
人们往往忘记的一个很大的漏洞是程序必须阻止某种IO,例如任何GUI程序中的用户输入。在这些情况下,使用何种语言并不重要,因为您受到数据进入速率的限制,而不是处理数据的速度。在这种情况下,如果您使用C,Java,C#甚至Perl,这并不重要;你不能比数据进来更快。
另一个主要问题是使用垃圾收集而不使用正确的指针允许虚拟机进行许多其他语言不可用的优化。例如,JVM能够在堆上移动对象以对其进行碎片整理。这使得未来的分配更快,因为可以简单地使用下一个索引而不是在表中查找它。现代JVM也不必实际释放内存;相反,它们只是移动活动对象,当GC和死对象的花费内存基本上是免费恢复时。
这也引出了一个关于C的有趣观点,在C ++中更是如此。有一种设计理念是“如果你不需要它,你就不需要付钱”。问题是,如果你真的想要它,你最终会为此付出代价。例如,Java中的vtable实现往往比C ++实现好很多,因此虚函数调用要快得多。另一方面,你别无选择,只能在Java中使用虚拟功能,但它们仍然需要花费一些成本,但在使用大量虚拟功能的程序中,降低了成本。
答案 15 :(得分:4)
与工具和库不同的是语言。 C的可用库和编译器比新语言更老。你可能会认为这会使它们变慢,但是反过来。
这些库是在处理能力和内存非常宝贵的时候编写的。他们必须有效地编写非常才能完成工作。 C编译器的开发人员也花了很长时间为不同的处理器进行各种巧妙的优化。 C的成熟和广泛采用比同龄的其他语言具有显着的优势。与C不同的新工具相比,它也使C具有速度优势。
答案 16 :(得分:4)
运行速度最快的代码将是精心手工制作的机器代码。汇编程序几乎一样好。两者都是非常低级别的,并且需要大量编写代码来执行操作。 C略高于汇编程序。您仍然可以在实际机器中以非常低的级别控制事物,但是有足够的抽象使得编写它比组装器更快更容易。其他语言如C#和JAVA更加抽象。虽然汇编程序和机器代码被称为低级语言,但C#和JAVA(以及许多其他语言)被称为高级语言。 C有时被称为中级语言。
答案 17 :(得分:4)
很高兴看到旧的“C / C ++ 必须比Java快,因为Java被解释为”神话仍然活着并且在踢。 articles going back a few years以及more recent ones可以解释为什么this simply isn't always the case的概念或衡量标准。
当前的虚拟机实现(顺便说一下,而不仅仅是JVM)可以利用在程序执行期间收集的信息,在运行时使用各种技术动态调整代码:
和a variety of other adjustments基于知道代码实际在做什么,以及它正在运行的环境的实际特征。
答案 18 :(得分:4)
缺乏抽象是使C更快的原因。如果您编写输出语句,则确切知道发生了什么。如果你在java中编写一个输出语句,它将被编译为一个类文件,然后在引入抽象层的虚拟机上运行。缺乏面向对象的功能作为语言的一部分也增加了它减少生成代码的速度。如果你使用C作为面向对象的语言,那么你正在对诸如类,吸入等等的事情进行所有编码。这意味着要为每个人提供足够广泛的代码,其中包含大量的代码和性能要求,只需要编写你完成工作需要什么。
答案 19 :(得分:3)
我知道有很多人以漫长的方式说出来,但是:
C更快,因为它做得更少(对你而言)。
答案 20 :(得分:2)
回到好日子里,只有两种语言:编译和解释。
编译语言使用“编译器”来读取语言语法并将其转换为相同的汇编语言代码,而不仅仅是直接在CPU上。解释语言使用了几种不同的方案,但基本上语言语法被转换为中间形式,然后在“解释器”(一种用于执行代码的环境)中运行。
因此,从某种意义上说,代码和机器之间还有另一个“层” - 解释器。而且,与计算机中的情况一样,更多意味着可以使用更多资源。口译人员较慢,因为他们必须执行更多操作。
最近,我们看到了更多混合语言,如Java,它们使用编译器和解释器来使它们工作。它很复杂,但是JVM比旧的解释器更快,更复杂并且更优化,因此它更接近于直接编译代码,表现更好(随着时间的推移)。当然,较新的编译器也有更多花哨的优化技巧,因此它们倾向于生成比以前更好的代码。但是大多数优化,通常(尽管不总是)进行某种类型的权衡,使得它们在所有情况下并不总是更快。像其他一切一样,没有任何东西是免费的,所以优化器必须从某个地方获得自夸(尽管通常使用编译时CPU来节省运行时CPU)。
回到C,它是一种简单的语言,可以编译成相当优化的程序集,然后直接在目标机器上运行。在C中,如果你增加一个整数,那么很可能它只是CPU中的一个汇编程序步骤,但是,它最终可能会比这更多(并且可能包括一些垃圾收集: - )C为您提供了一种更接近机器的抽象(汇编程序是最接近的),但您最终必须采取更多的工作来实现它并且它不受保护,易于使用或错误友好。大多数其他语言为您提供更高的抽象,并为您处理更多基础细节,但作为交换其高级功能,它们需要更多资源才能运行。在概括某些解决方案时,您必须处理更广泛的计算,这通常需要更多资源。
保罗。
答案 21 :(得分:2)
不要对某些人说话,在代码的任何性能关键部分中查看C和您选择语言的反汇编。 我认为您可以在运行时在Visual Studio中查看反汇编窗口以查看反汇编的.Net。如果使用windbg对Java有用,应该是可能的,但是如果你用.Net做的话,很多问题都是一样的。
如果我不需要,我不喜欢用C语言写作,但是我认为在这些答案中提出的许多声明可以通过简单地拆解相同的程序来放弃C语言以外的语言速度。在C和您选择的更高级语言中,特别是如果涉及大量数据,这在性能关键应用程序中很常见。 Fortran可能是其专业领域的一个例外,不知道。它的水平是否高于C?
我第一次将JITed代码与本机代码进行了比较,解决了.Net代码是否可以与C代码进行比较的问题。额外的抽象级别和所有安全检查都会带来巨大的成本。相同的成本可能适用于Java,但不要相信我的意思,在性能至关重要的事情上尝试。 (任何人都对JITed Java有足够的了解,可以在内存中找到一个已编译的程序吗?它应该是可能的)
答案 22 :(得分:1)
使用现代优化编译器,纯C程序比编译的.net代码要快得多,如果有的话。随着.net等框架为开发人员提供的生产力提升,您可以在一天中做一些过去需要数周或数月的常规C。再加上硬件的廉价成本与开发人员的工资相比,它只是 WAY 以高级语言编写内容并以任何缓慢的速度抛出硬件会更便宜。
Jeff和Joel谈论C是“真正的程序员”语言的原因是因为C中没有手持。你必须分配自己的内存,释放内存,进行自己的边界检查等等。没有新对象();没有垃圾收集,类,OOP,实体框架,LINQ,属性,属性,字段或类似的东西。你必须知道指针算术和如何取消引用指针之类的东西。并且,就此而言,了解并理解指针是什么。您必须知道堆栈帧是什么以及指令指针是什么。您必须知道正在处理的CPU架构的内存模型。在使用C语言进行编程时,在使用C语言进行编程时,对于微型计算机(通常是 微型计算机)的体系结构有很多隐含的理解。所有这些信息都已卸载到编译器(或VM)程序员。
答案 23 :(得分:1)
1)正如其他人所说,C对你的影响较小。没有初始化变量,没有数组边界检查,没有内存管理等。其他语言中的这些功能会花费C不会花费的内存和CPU周期。
2)答案说C抽象较少,因此速度更快我认为只有一半是正确的。从技术上讲,如果你有一个语言X的“足够先进的编译器”,那么语言X可以接近或等于C的速度。与C的区别在于,因为它的映射非常明显(如果你已经参加了一个架构课程)直接使用汇编语言,即使是一个天真的编译器也能做得不错。对于像Python这样的东西,你需要一个非常先进的编译器来预测可能的对象类型并动态生成机器代码 - C语义很简单,简单的编译器就可以做得很好。
答案 24 :(得分:1)
某些C ++算法比C更快,其他语言的算法或设计模式的某些实现可能比C更快。
当人们说C很快,然后继续谈论其他语言时,他们通常会将C的表现作为基准。
答案 25 :(得分:1)
这是自动和手动之间的区别,更高级别的语言是抽象的,因此是自动化的。手动控制和处理C / C ++,甚至错误检查代码有时也是手工劳动。
C和C ++也是编译语言,这意味着没有任何一种语言可以在任何地方运行,这些语言必须针对您使用的硬件进行微调,从而增加了一层额外的问题。虽然C / C ++编译器在所有平台上变得越来越普遍,但现在有点茫然。您可以在平台之间进行交叉编译。它仍然不是一个无处不在的运行情况,你基本上指示编译器A针对编译器B编译相同代码的不同架构。
底线C语言并不易于理解或推理,这也是他们称之为系统语言的原因。他们在所有这些高级抽象废话之前就出来了。这也是他们不用于前端Web编程的原因。他们只是不适合这项任务,他们的意思是解决传统语言工具无法解决的复杂问题。
这就是为什么你会得到疯狂的东西(微架构,驱动程序,量子物理,AAA游戏,操作系统),有些东西很适合C和C ++。速度和数字运算是主要领域。
答案 26 :(得分:1)
Setting aside advanced optimization techniques such as hot-spot optimization, pre-compiled meta-algorithms, and various forms of parallelism, the fundamental speed of a language correlates strongly with the implicit behind-the-scenes complexity required to support the operations that would commonly be specified within inner loops.
Perhaps the most obvious is validity checking on indirect memory references -- such as checking pointers for if (key.length >= 1)
and checking indexes against array boundaries. Most high-level languages perform these checks implicitly, but C does not. However, this is not necessarily a fundamental limitation of these other languages -- a sufficiently clever compiler may be capable of removing these checks from the inner loops of an algorithm through some form of loop-invariant code motion.
The more fundamental advantage of C (and to a similar extent the closely related C++) is a heavy reliance on stack-based memory allocation, which is inherently fast for allocation, deallocation, and access. In C (and C++) the primary call stack can be used for allocation of primitives, arrays, and aggregates (null
/struct
).
While C does offer the capability to dynamically allocate memory of arbitrary size and lifetime (using the so called 'heap'), doing so is avoided by default (the stack is used instead).
Tantalizingly, it is sometimes possible to replicate the C memory allocation strategy within the runtime environments of other programming languages. This has been demonstrated by asm.js, which allows code written in C or C++ to be translated into a subset of JavaScript and run safely in a web browser environment -- with near-native speed.
As somewhat of an aside, another area where C and C++ outshine most other languages for speed is the ability to seamlessly integrate with native machine instruction sets. A notable example of this is the (compiler and platform dependent) availability of SIMD intrinsics which support the construction of custom algorithms that take advantage of the now nearly ubiquitous parallel processing hardware -- while still utilizing the data allocation abstractions provided by the language (lower-level register allocation is managed by the compiler).
答案 27 :(得分:1)
我在链接上找到了关于为什么有些语言更快而有些语言更慢的答案,我希望这将更清楚地说明为什么C或C ++比其他语言更快,还有一些其他语言也比C快,但是我们不能全部使用它们。一些解释 -
Fortran仍然很重要的一个重要原因是因为它很快:用Fortran编写的数字运算程序往往比用大多数其他语言编写的等效例程更快。使用在这个空间C和C ++中与Fortran竞争的语言是因为它们与这种性能竞争。
这提出了一个问题:为什么?什么是C ++和Fortran使它们快速,为什么它们优于其他流行语言,如Java或Python?
解释与编译 根据他们鼓励的编程风格和他们提供的功能,有许多方法可以对编程语言进行分类和定义。在查看性能时,最大的区别在于解释语言和编译语言。
分歧并不难;相反,有一个频谱。一方面,我们有传统的编译语言,包括Fortran,C和C ++。在这些语言中,有一个离散的编译阶段,它将程序的源代码转换为处理器可以使用的可执行形式。
此编译过程包含几个步骤。分析和解析源代码。此时可以检测到拼写错误和拼写错误等基本编码错误。解析后的代码用于生成内存中表示,也可用于检测错误 - 这次是语义错误,例如调用不存在的函数,或者尝试对文本字符串执行算术运算
然后,这种内存中表示用于驱动代码生成器,即生成可执行代码的部分。在此过程中的不同时间执行代码优化以提高生成代码的性能:可以对代码表示执行高级优化,并在代码生成器的输出上使用低级优化。
实际执行代码后会发生。整个编译过程只是用来创建可以执行的东西。
在另一端,我们有口译员。解释器将包含一个类似于编译器的解析阶段,但这会用于驱动直接执行,程序会立即运行。
最简单的解释器在其中包含与语言支持的各种功能相对应的可执行代码 - 因此它将具有添加数字,连接字符串以及给定语言所具有的任何其他功能的功能。在解析代码时,它将查找相应的函数并执行它。程序中创建的变量将保存在某种查找表中,该表将其名称映射到数据中。
解释器样式的最极端的例子类似于批处理文件或shell脚本。在这些语言中,可执行代码通常甚至不构建在解释器本身中,而是构建在独立的独立程序中。
那么为什么这会对性能产生影响呢?通常,每个间接层都会降低性能。例如,添加两个数字的最快方法是在处理器的寄存器中同时包含这两个数字,并使用处理器的add指令。这是编译程序可以做的事情;他们可以将变量放入寄存器并利用处理器指令。但是在解释程序中,相同的添加可能需要在变量表中进行两次查找以获取要添加的值,然后调用函数来执行添加。该函数很可能使用与编译程序用于执行实际添加的相同处理器指令,但实际使用指令之前的所有额外工作会使事情变慢。
如果您想了解更多信息,请查看Source
答案 28 :(得分:0)
C快速,因为它是本机编译的低级语言。但是C并不是最快的。 Recursive Fibonacci Benchmark表明Rust,Crystal和Nim可以更快。
答案 29 :(得分:0)
这都是关于时间和精力的。
给予无限的时间和精力:
给定一定的时间和精力:
为什么呢?因为你做的抽象越多,你就可以花更多的时间来优化真正重要的代码的关键部分。这里的一些假设是开发人员在所有三种语言中同样胜任,你不关心二进制大小,内存使用等。
每个抽象都具有成本效益,但应该使代码更容易,更快速地编写。
答案 30 :(得分:0)
原因很多,包括:
答案 31 :(得分:0)
实际上,在某些应用程序(数字)中,即使C也可以被打败,我不是指汇编语言,而是旧的,经常被嘲笑的Fortran。原因是,Fortran保证没有指针别名。
答案 32 :(得分:0)
只需逐步浏览IDE中的机器代码,您就会明白为什么它更快(如果它更快)。它省去了很多手。有可能你的Cxx也被告知要把它留下来,在这种情况下应该大致相同。
编译器优化被高估,几乎所有关于语言速度的看法都被高估了。
生成代码的优化只会对热点代码产生影响,即缺乏函数调用(显式或隐式)的紧密算法。在其他地方,它实现的很少。
答案 33 :(得分:0)
即使C和C ++之间的差异有时也很大。
当你为一个对象分配内存,调用构造函数,在字边界上对齐内存等时,程序最终会经历从程序员那里抽象出来的大量开销。
C强迫你看一下你的程序正在做的每件事情,通常是非常精细的细节。这使得编写执行许多任务的代码变得更加困难(尽管绝不是不可能),而这些任务对于眼前的目标来说是不必要的。
那么在哪里,例如BASIC程序,你将使用INPUT关键字读取字符串形式STDIN并自动为其变量分配内存,在C中程序员通常已经分配了内存并可以控制程序是否是程序是否有I / O块,如果它在获得所需信息后停止读取输入,或者继续读取行尾的字符。
与其他语言相比,C语言执行的错误检查要少得多,假设程序员知道他们在做什么。因此,在PHP中,如果您声明一个字符串$myStr = getInput();
并继续引用$myStr[20]
,但输入只有10个字符长,PHP将捕获这个并安全地返回给您一个空白字符串。 C假设您已经分配了足够的内存来保存数据超出字符串的结尾,或者您知道字符串后面有什么信息并且正在尝试引用它。这些小因素对总体开销产生巨大影响。