为什么C如此之快,为什么不是其他语言更快或更快呢?
在听StackOverflow播客时,Jab不停地提到“真正的程序员”用C编写,而C更快,因为它“接近机器”。 把前面的断言留给另一篇文章,C的特别之处在于它比其他语言更快呢? 或者换一种说法:阻止其他语言能够编译成与C一样快速运行的二进制文件?
C没有什么特别之处,这是快速的原因之一。
新的语言支持垃圾收集 , dynamicinput和其他便于程序员编写程序的工具。
问题是,还有额外的处理开销会降低应用程序的性能。 C没有这个意思,这意味着没有任何开销,但这意味着程序员需要能够分配内存并释放它们来防止内存泄漏 ,并且必须处理variables的静态types。
也就是说,Java(带有Java虚拟机 )和.NET(带有它的公共语言运行时)等多种语言和平台,多年来随着诸如即时编译(即时生成本机代码)字节码来实现更高的性能。
Cdevise师做了一个交易。 也就是说,他们决定把速度放在安全之上。 C不会
- 检查数组索引的绑定
- 检查未初始化的variables值
- 检查内存泄漏
- 检查空指针解引用
当你索引到一个数组中时,在Java中它需要在虚拟机中进行一些方法调用,绑定检查和其他健全性检查。 这是有效的,绝对好 ,因为它增加了安全的地方。 但是在C中,即使是很琐碎的东西也没有安全。 例如,C不需要memcpy来检查要复制的区域是否重叠。 它不是作为编程大型商业应用程序的语言而devise的。
但是这些devise决定并不是C语言中的错误 。 它们是通过devise的,因为它允许编译器和库编写者从计算机中获得每一点性能。 这里是C原理文件解释它的精神:
C代码可以是不可移植的。 尽pipe它努力给程序员提供编写真正可移植程序的机会,委员会并不希望强制程序员写作,以防止将C用作“高级汇编程序”:编写特定于机器的程序代码是C的强项之一
保持C的精神。委员会始终把保持C的传统精神作为主要目标。C的精神有很多方面,但本质是C语言所依据的基本原则的社会情感。 C的精神的一些方面可以总结为像
- 相信程序员。
- 不要阻止程序员去做需要做的事情。
- 保持语言小而简单。
- 只提供一种方法来执行操作。
- 快速,即使不能保证便携。
最后一句谚语需要一点解释。 有效的代码生成的可能性是C的最重要的优势之一。为了确保看起来非常简单的操作没有发生代码爆炸,许多操作被定义为目标机器的硬件如何执行,而不是一个通用的抽象规则。 在规则中可以看到这种愿意接受机器所做的事情的例子,这些规则决定了在expression式中使用的char对象的扩展:char对象的值是否扩大为有符号或无符号数量,通常取决于哪个字节操作更多在目标机器上高效。
如果花费一个月的时间在C中创build一些运行时间为0.05秒的东西,那么我花了一天的时间在Java中编写相同的东西,运行时间为0.10秒,那么C真的更快吗?
但是要回答你的问题, 编写良好的 C代码通常比其他语言中编写得好的代码运行得更快,因为编写C代码的一部分“很好”包括在接近机器级别进行手动优化。
尽pipe编译器确实非常聪明,但他们还不能创造性地提出与手按摩algorithm竞争的代码(假设“手”属于一个优秀的 C程序员)。
编辑:
很多评论都是“我用C写的,我不考虑优化”。
但是从这个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;
在CI写这个:
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版本中有多less优化? 在Delphi版本中我们做了很多关于实现的决定, string是如何实现的? 在delphi,我没有看到它。 在C中,我已经决定它将是一个指向一个ASCII整数的指针,我们称之为字符。 在C中,我们一次testing一个angular色存在。 在Delphi中,我使用Pos。
这只是一个小例子。 在一个大的程序中,一个C程序员必须用几行代码来做出这样的低级决定。 它增加了一个手工制作的手动优化的可执行文件。
我没有看到它,所以我会说: C往往会更快,因为几乎所有的东西都写在C中 。
Java是build立在C上的,Python是build立在C(或者Java,或者.NET等)上,Perl是等等。OS是用C编写的,虚拟机是用C编写的,编译器是用C编写的,译员用C写成。有些东西还是用汇编语言编写的,而汇编语言往往更快。 越来越多的东西正在写在别的东西上,这本身就是用C写成的。
您用其他语言(不是汇编语言)编写的每条语句通常在C语言中作为几个语句实现,这些语句被编译为本地机器代码。 由于为了获得比C更高级别的抽象,倾向于存在其他语言,所以C中所需的额外语句倾向于关注于增加安全性,增加复杂性和提供error handling。 这些往往是好东西,但他们有成本 ,其名称是速度和大小 。
就我个人而言,我用几十种语言编写了大量可用的语言,而且我个人也在寻找你所暗示的魔法:
我怎么可以吃我的蛋糕,吃呢? 如何用我最喜欢的语言进行高层次的抽象,然后下降到C的速度?
经过几年的研究,我的答案是Python(C语言)。 你可能想看看它。 顺便说一句,你也可以从Python中下载到汇编(也可以从一个特殊的库中获得一些小的帮助)。
另一方面, 错误的代码可以用任何语言编写 。 因此,C(或汇编)代码不会自动加快。 同样,一些优化技巧可以使部分更高级的语言代码接近原始C的性能水平。但是,对于大多数应用程序,您的程序大部分时间都花在等待人员或硬件上,所以差异并不重要。
请享用。
那里有很多问题 – 大多数我没有资格回答。 但是对于最后一个:
什么是阻止其他语言能够编译到二进制运行的每一位一样快C?
总之,抽象。
C只是一个或两个抽象层面的机器语言。 Java和.Net语言至less有3个抽象层级,远离汇编程序。 我不确定Python和Ruby。
通常,程序员玩具越多(复杂的数据types等等),机器语言就越多,翻译也就越多。
我在这里,但这是基本的要点。
更新 – 有关此post的一些很好的评论与更多的细节。
与C的成本模型是透明的相比 ,C不是那么快。 如果一个C程序很慢,显然很慢:通过执行很多语句。 与C中的操作成本相比,对象(特别是reflection)或string的高级操作可能具有不明显的成本。
通常编译为与C一样快的二进制文件的两种语言是Standard ML(使用MLton编译器)和Objective Caml 。 如果你看看Great Language Shootout,你会发现对于一些基准testing,比如二叉树,OCaml版本比C版本更快(我没有find任何MLton条目)。但是不要太认真地对待枪战。 正如它所说的,它是一个游戏,结果往往反映了人们在调整代码方面付出了多less努力。
C并不总是更快。
C比现在的Fortran慢。
在某些情况下,C通常比Java慢。 (特别是在JIT编译器已经在你的代码中去了之后)
C让指针别名发生,这意味着一些好的优化是不可能的。 特别是当你有多个执行单元时,这会导致数据提取失速。 噢。
指针algorithm的工作原理确实会导致某些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上使用。
什么是阻止其他语言能够编译到二进制运行的每一位一样快C?
没有。 像Java或.NET语言这样的现代语言,更多地依赖于程序员的生产力而不是性能。 硬件现在很便宜。 另外,编译为中间表示还提供了许多奖励,如安全性,可移植性等。.NET CLR可以利用不同的硬件 – 例如,您不需要手动优化/重新编译程序来使用SSE指令集。
主要的因素是它是一种静态types的语言,它被编译成机器码。 另外,因为它是低级语言,所以它通常不会做任何你没有告诉它的事情。
这些是想到的其他一些因素。
- variables不会自动初始化
- 没有边界检查数组
- 未经检查的指针操纵
- 没有整数溢出检查
- 静态types的variables
- 函数调用是静态的(除非你使用函数指针)
- 编译器编写者有很多时间来改进优化代码。 另外,为了获得最佳性能,人们使用C语言进行编程,所以优化代码是有压力的。
- 语言规范的一部分是实现定义的,所以编译器可以自由地以最优的方式做事情
大多数静态types语言可以被编译得比C快或者更快,特别是如果他们可以假设C不能因为指针混叠等原因
我想你忘了汇编语言也是一种语言:)
但是严重的是,只有程序员知道他在做什么,C程序才会更快。 您可以轻松编写一个C程序,其运行速度比使用其他语言编写的程序运行得更慢。
C更快的原因是因为它是这样devise的。 它可以让你做很多“低级”的东西,帮助编译器优化代码。 或者,我们可以说,程序员负责优化代码。 但是这往往是非常棘手和容易出错的。
其他语言,就像其他语言一样,更多地关注程序员的生产力。 人们普遍认为,程序员的时间比机器时间(即使在过去的时间)贵得多。 因此,尽量减less程序员在编写和debugging程序上花费的时间,而不是程序的运行时间。 要做到这一点,你会牺牲一些你可以做什么来使程序更快,因为很多东西都是自动的。
我不认为有人提到这样一个事实,即比其他任何编译器都付出了更多的努力,可能是Java的例外。
由于已经陈述的许多原因,C是非常优化的 – 比其他任何语言都要多。 所以如果把相同的努力放到其他语言编译器中,C可能仍然会排在前面。
我认为至less有一个候选语言的努力可以比C更好的优化,因此我们可以看到生成更快的二进制文件的实现。 我正在考虑数字火星D,因为创build者注意构build一种可能比C更好的语言。可能有其他语言有这种可能性。 但是我无法想象任何语言的编译器都会比最好的C编译器快几个百分点。 我很想做错。
我认为真正的“低垂的果实”将会被devise为易于人类优化的语言。 一个熟练的程序员可以让任何语言都变得更快 – 但是有时你必须做一些荒谬的事情,或者使用不自然的构造来实现这一点。 尽pipe总是需要付出努力,但一个好的语言应该能够产生相对较快的代码,而不必过多地关心程序的写法。
(至less对我来说)最糟糕的情况代码往往很快。 Java在网上有许多“certificate”,比Java更快或更快,但这是基于樱桃采摘的例子。 我不是C的忠实粉丝,但是我知道我用C写的任何东西都会运行良好。 对于Java来说,它可能会以15%的速度运行,通常在25%以内,但在某些情况下可能更糟糕。 任何情况下,一样快或在百分之几之内,通常是由于大部分时间花费在大量优化C的库代码上。
大多数情况下,每个C指令对应于很less的汇编指令。 你基本上是在编写更高级别的机器代码,所以你可以控制处理器几乎所有的东西。 许多其他的编译语言,比如C ++,都有很多简单的指令,可以变成比你想象的更多的代码(虚拟函数,拷贝构造函数等等)。像Java或者Ruby这样的解释语言还有另外一层你永远不会看到的指令 – 虚拟机或解释器。
这实际上是一个长久的谎言。 虽然C程序的速度确实很快,但事实并非总是如此,特别是如果C程序员不擅长。
人们往往忘记的一个大问题就是程序不得不阻止某种IO,比如任何GUI程序中的用户input。 在这些情况下,使用哪种语言并不重要,因为受数据访问速度的限制,而不是用多快的速度进行处理。 在这种情况下,如果您使用C,Java,C#甚至Perl,则无关紧要。 你不能比数据进入更快。
另一个重要的事情是使用垃圾收集,而不使用正确的指针允许虚拟机进行一些优化,其他语言不可用。 例如,JVM能够在堆上移动对象以对其进行碎片整理。 这使得未来的分配速度更快,因为下一个索引可以简单地使用,而不是在表中查找。 现代JVM也不必实际释放内存; 相反,他们只是移动活动对象时,他们GC和从死对象的已用内存基本上是免费的恢复。
这也提出了关于C的一个有趣的观点,在C ++中更是如此。 有一种devise理念是“如果你不需要它,你就不用付钱”。 问题是,如果你确实需要它,你最终会为此付出代价。 例如,Java中的vtable实现比C ++实现要好得多,所以虚函数调用要快得多。 另一方面,你别无select,只能在Java中使用虚拟function,而且还会花费一些东西,但是在使用大量虚拟function的程序中,成本增加了。
许多这些答案给出了为什么C是或者不是更快(无论是在一般还是在特定情况下)的正当理由。 不可否认的是:
- 许多其他语言提供我们认为理所当然的自动function。 例如,边界检查,运行时types检查和自动内存pipe理不是免费的。 至less有一些与这些function相关的成本,在编写使用这些function的代码时,我们可能不会考虑甚至意识到这些成本。
- 从源代码到机器的步骤通常不像C语言那样直接。
- OTOH,说编译的C代码比用其他语言编写的其他代码执行得更快是一种泛化,并不总是正确的。 反例很容易find(或devise)。
尽pipe如此,还有一些我注意到的是,我认为,与其他任何因素相比,C和其他语言的比较performance都会更大。 以机智:
其他语言通常可以更容易地编写执行更慢的代码。 语言的devise哲学常常甚至鼓励它。 推论:C程序员更可能编写不执行不必要操作的代码。
作为一个例子,考虑一个简单的Windows程序,其中创build一个主窗口。 AC版本将填充WNDCLASS[EX]
结构,该结构将被传递给RegisterClass[Ex]
,然后调用CreateWindow[Ex]
并input消息循环。 高度简化和缩写的代码如下:
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代码所做的所有function,并添加了一些我们遗漏的内容,例如错误检查。 更丰富,更丰富的库(与那些在典型的C项目中使用的库相比)为我们做了很多工作,使我们有更多的时间去编写更多的代码片断,这些代码片段对我们来说很短暂,但涉及幕后很多步骤。
但是,一个丰富的库,使代码膨胀容易和快速并不是我的观点。 当我们开始审视实际执行小class的实际情况时,我的观点更为明显。 为了好玩,在Visual Studio 2008或更高版本中启用.NET源代码访问 ,并进入上面的简单的one-linef。 你会遇到的一个有趣的小gem是在Control.CreateParams
的getter中的这个注释:
// 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
结构中并传递给RegisterClassEx
和CreateWindowEx
之前 ,从Control
类检索大约相当于存储在WNDCLASSEX
结构中的内容和传递给CreateWindowEx
内容的信息十次。
总而言之,执行这一非常基本任务的指令数量在C#中要比在C中多2-3个数量级。部分原因是由于使用了一个function丰富的库,我们简单的C代码正是我们所需要的,只不过是我们所需要的。 但是其中的一部分原因是.NET框架的模块化,面向对象的特性,使得自身往往被程序方法所避免的执行的重复。
我没有试图selectC#或.NET框架。 我也不是说模块化,泛化,图书馆/语言特征,面向对象等是不好的东西 。 我曾经在C语言中做过大部分的开发工作,后来在C ++中做了大部分工作,最近在C#中做了大部分工作。 同样,在C之前,我大部分都是使用程序集。 随着语言的每一步“更高”,我会在更短的时间内写出更好,更可维护,更强大的程序。 然而,他们的确执行起来要慢一些。
C ++平均速度更快(因为它最初是C的超集)。 但是对于特定的基准,通常还有另一种语言更快。
http://shootout.alioth.debian.org/u32/benchmark.php
fannjuch-redux在Scala中是最快的
在Ada中,n-body,fasta更快。
在Fortran中,谱范数是最快的。
反向补充,mandelbrot,pidigits在ATS中是最快的。
正则expression式在JavaScript中是最快的。
chameneou-redux最快的是Java 7。
线程环在Haskell中是最快的。
其余的基准在C或C ++中是最快的。
抽象的缺乏使得C更快。 如果你写一个输出语句,你确切地知道发生了什么。 如果你用java编写输出语句,它将被编译成一个类文件,然后在一个引入抽象层的虚拟机上运行。 作为语言的一部分缺乏面向对象的function也增加了速度,以减less代码的产生。 If you use C as an object oriented language then you are doing all the coding for things such as classes, inharitence, etc. This means rather then make something generalized enough for everyone with the amount of code and the performance penelty that requires you only write what you need to get the job done.
Amazing to see the old "C/C++ must be faster than Java because Java is interpreted" myth is still alive and kicking. There are articles going back a few years , as well as more recent ones , that explain with concepts or measurements why this simply isn't always the case .
Current virtual machine implementations (and not just the JVM, by the way) can take advantage of information gathered during program execution to dynamically tune the code as it runs, using a variety of techniques:
- rendering frequent methods to machine code,
- inlining small methods,
- adjustment of locking
and a variety of other adjustments based on knowing what the code is actually doing, and on the actual characteristics of the environment in which it's running.
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.
It's not so much about the language as the tools and libraries. The available libraries and compilers for C are much older than for newer languages. You might think this would make them slower, but au contraire.
These libraries were written at a time when processing power and memory were at a premium. They had to be written very efficiently in order to work at all. Developers of C compilers have also had a long time to work in all sorts of clever optimizations for different processors. C's maturity and wide adoption makes for a signficant advantage over other languages of the same age. It also gives C a speed advantage over newer tools that don't emphasize raw performance as much as C had to.
I know plenty of people have said it in a long winded way, but:
C is faster because it does less (for you).
Back in the good ole days, there were just two types of languages: compiled and interpreted.
Compiled languages utilized a "compiler" to read the language syntax and convert it into identical assembly language code, which could than just directly on the CPU. Interpreted languages used a couple of different schemes, but essentially the language syntax was converted into an intermediate form, and then run in a "interpreter", an environment for executing the code.
Thus, in a sense, there was another "layer" — the interpreter — between the code and the machine. And, as always the case in a computer, more means more resources get used. Interpreters were slower, because they had to perform more operations.
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.
保罗。
Some C++ algorithms are faster than C, and some implementations of algorithms or design patterns in other languages can be faster than C.
When people say that C is fast, and then move on to talking about some other language, they are generally using C's performance as a benchmark.
With modern optimizing compilers, it's highly unlikely that a pure C program is going to be all that much faster than compiled .net code, if at all. With the productivity enhancement that frameworks like .net provide the developer, you can do things in a day that used to take weeks or months in regular C. Coupled with the cheap cost of hardware compared to a developer's salary, it's just WAY cheaper to write the stuff in a high-level language and throw hardware at any slowness.
The reason Jeff and Joel talk about C being the "real programmer" language is because there is no hand-holding in C. You must allocate your own memory, deallocate that memory, do your own bounds-checking, etc. There's no such thing as new object(); There's no garbage collection, classes, OOP, entity frameworks, LINQ, properties, attributes, fields, or anything like that. You have to know things like pointer arithmetic and how to dereference a pointer. And, for that matter, know and understand what a pointer is. You have to know what a stack frame is and what the instruction pointer is. You have to know the memory model of the CPU architecture you're working on. There is a lot of implicit understanding of the architecture of a microcomputer (usually the microcomputer you're working on) when programming in C that simply is not present nor necessary when programming in something like C# or Java. All of that information has been off-loaded to the compiler (or VM) programmer.
1) As others have said, C does less for you. No initializing variables, no array bounds checking, no memory management, etc. Those features in other languages cost memory and CPU cycles that C doesn't spend.
2) Answers saying that C is less abstracted and therefore faster are only half correct I think. Technically speaking, if you had a "sufficiently advanced compiler" for language X, then language X could approach or equal the speed of C. The difference with C is that since it maps so obviously (if you've taken an architecture course) and directly to assembly language that even a naive compiler can do a decent job. For something like Python, you need a very advanced compiler to predict the probable types of objects and generate machine code on the fly — C's semantics are simple enough that a simple compiler can do well.
Don't take someones word for it, look at the dissassembly for both C and your language-of-choice in any performance critical part of your code. I think you can just look in the disassembly window at runtime in Visual Studio to see disassembled .Net. Should be possible if tricky for Java using windbg, though if you do it with .Net many of the issues would be the same.
I don't like to write in C if I don't need to, but I think many of the claims made in these answers that tout the speed of languages other than C can be put aside by simply disassembling the same routine in C and in your higher level language of choice, especially if lots of data is involved as is common in performance critical applications. Fortran may be an exception in its area of expertise, don't know. Is it higher level than C?
First time I did compared JITed code with native code resolved any and all questions whether .Net code could run comparably to C code. The extra level of abstraction and all the safety checks come with a significant cost. Same costs would probably apply to Java, but don't take my word for it, try it on something where performance is critical. (Anyone know enough about JITed Java to locate a compiled procedure in memory? It should certainly be possible)
It's the difference between automatic and manual, higher level languages are abstractions thus automated. C/C++ are manually controlled and handled, even error checking code is sometimes a manual labor.
C and C++ are also compiled languages which means none of that run everywhere business, these languages have to be fine tuned for the hardware you work with thus adding an extra layer of gotcha. Though this is slightly fazing out now as C/C++ compilers are becoming more common across all platforms. You can do cross compilations between platforms. It's still not a run everywhere situation, your basically instructing compiler A to compile against compiler B same code different architecture.
Bottom line C languages are not meant to be easy to understand or reason, this is also why their referred to as systems languages. They came out before all this high level abstraction nonsense. This is also why they are not used for front end web programming. Their just not suited to the task, their mean to solve complex problems that can't be resolved with conventional language tooling.
This is why you get crazy stuff like (micro-architectures, drivers, quantum physics, AAA Games, operating systems) there are things C and C++ are just well suited for. Speed and number crunching being the chief areas.
Even the difference between C and C++ can at times be great.
When you are allocating memory for an object, invoking constructors, aligning memory on word boundaries, etc. the program winds up going through a lot of overhead that is abstracted away from the programmer.
C forces you to take a look at each thing that your program is doing, generally at a very fine level of detail. This makes it harder (although not by any means impossible) to write code that does a lot of tasks that are unnecessary to the immediate goal at hand.
So where in, for instance a BASIC program you would use the INPUT keyword to read a string form STDIN and automatically allocate memory for its variable, in C the programmer will typically have already allocated memory and can control things like whether the program blocks for I/O or not, and if it stops reading input after it has the information it needs or continues reading characters to the end of the line.
C also performs a lot less error-checking than other languages, presuming the programmer knows what they're doing. So whereas in PHP if you declare a string $myStr = getInput();
and go on to reference $myStr[20]
, but the input was only 10 characters long, PHP will catch this and safely return to you a blank string. C assumes that you've either allocated enough memory to hold data past the end of the string or that you know what information comes after the string and are trying to reference that instead. These small factors have a huge impact on overhead in aggregate.
Just step through the machine code in your IDE, and you'll see why it's faster (if it's faster). It leaves out a lot of hand-holding. Chances are your Cxx can also be told to leave it out too, in which case it should be about the same.
Compiler optimizations are overrated, as are almost all perceptions about language speed.
Optimization of generated code only makes a difference in hotspot code, that is, tight algorithms devoid of function calls (explicit or implicit). Anywhere else, it achieves very little.
Actually, in certain applications (numerics) even C can be beaten, and I don't mean assembly language, but the old, oft-ridiculed Fortran. The reason is, Fortran guarantees no pointer aliasing.