在听StackOverflow播客的时候,经常有人说“真正的程序员”是用C语言编写的,而C语言的速度要快得多,因为它“接近机器”。把前面的断言留到另一篇文章,C有什么特别之处,使它比其他语言更快?或者换句话说:什么能阻止其他语言编译成二进制代码,使其运行速度与C语言一样快?
当前回答
C语言并不总是更快。
C语言比现代Fortran语言慢。
在某些方面,C通常比Java慢。(特别是在JIT编译器对您的代码进行了测试之后)
C允许发生指针混叠,这意味着一些好的优化是不可能的。特别是当您有多个执行单元时,这将导致数据获取停滞。噢。
指针算术工作的假设确实会导致某些CPU系列(特别是PIC !)它曾经在x86上很差劲。
基本上,当你得到一个矢量单元,或者一个并行编译器,C语言很糟糕,而现代的Fortran运行得更快。
C程序员的一些技巧,比如thking(动态修改可执行文件)会导致CPU预取暂停。
明白我的意思了吗?
而我们的好朋友x86执行的指令集,如今与实际的CPU架构关系不大。影子寄存器,负载存储优化器,都在CPU中。所以C离虚拟金属很近。真正的金属,英特尔不会让你看到。(从历史上看,VLIW CPU有点破产,所以,也许这并不是那么糟糕。)
如果你在高性能DSP上用C编程(可能是TI DSP ?),编译器必须做一些棘手的事情,在多个并行执行单元之间展开C。因此,在这种情况下,C语言并不接近金属,但它接近编译器,它将进行整个程序优化。奇怪。
最后,一些cpu (www.ajile.com)在硬件中运行Java字节码。C将在该CPU上使用一个PITA。
其他回答
我还没有看到它,所以我要说:C往往更快,因为几乎所有其他东西都是用C写的。
Java是建立在C上的,Python是建立在C上的(或者Java,或者。net等等),Perl是等等。操作系统是用C写的,虚拟机是用C写的,编译器是用C写的,解释器是用C写的,有些东西仍然是用汇编语言写的,这往往更快。越来越多的东西是用别的东西写的,而这些东西本身就是用C写的。
您用其他语言(不是Assembly)编写的每个语句通常都在下面实现为C中的几个语句,这些语句被编译为本机机器代码。由于其他语言的存在往往是为了获得比C更高的抽象级别,因此C中所需的那些额外语句往往侧重于增加安全性、增加复杂性和提供错误处理。这些通常都是好事,但它们是有代价的,那就是速度和规模。
就我个人而言,我已经用几十种语言写过了,涵盖了大部分可用的范围,我个人也一直在寻找你暗示的魔法:
我怎样才能鱼与熊掌兼得呢?我如何在我最喜欢的语言中玩高级抽象,然后为了速度而降至C语言的细节?
经过几年的研究,我的答案是Python(在C上)。你可能想看看它。顺便说一下,您也可以从Python下拉到Assembly(从一个特殊的库中获得一些小小的帮助)。
另一方面,任何语言都可能编写出糟糕的代码。因此,C(或汇编)代码不会自动更快。同样,一些优化技巧可以使部分高级语言代码的性能水平接近原始c语言的性能水平。但是,对于大多数应用程序来说,程序的大部分时间都在等待人员或硬件,因此两者之间的差异实际上并不重要。
享受。
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一样快?
没什么。像Java或。net语言这样的现代语言更多地面向程序员的生产力,而不是性能。现在硬件很便宜。此外,编译到中间表示提供了很多好处,如安全性,可移植性等。net CLR可以利用不同的硬件-例如,你不需要手动优化/重新编译程序来使用SSE指令集。
这些答案中的许多都给出了为什么C更快或更快的有效理由(无论是在一般情况下还是在特定的场景中)。不可否认的是:
Many other languages provide automatic features that we take for granted. Bounds checking, run-time type checking, and automatic memory management, for example, don't come for free. There is at least some cost associated with these features, which we may not think about—or even realize—while writing code that uses these features. The step from source to machine is often not as direct in other languages as it is in C. OTOH, to say that compiled C code executes faster than other code written in other languages is a generalization that isn't always true. Counter-examples are easy to find (or contrive).
尽管如此,我还是注意到另一件事,我认为它比其他任何因素都更能影响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或更高版本中启用. net源代码访问,然后进入上面简单的一行代码。您将遇到的一个有趣的小珍宝是Control的getter中的这个注释。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的内容的总和,在它存储在WNDCLASSEX结构中并传递给RegisterClassEx和CreateWindowEx之前,从Control类中检索10次。
总而言之,在c#中执行这个非常基本的任务的指令数量比在C中多2-3个数量级,部分原因是使用了功能丰富的库,这是必然的,而我们简单的C代码只做了我们需要的事情,仅此而已。但部分原因是. net框架的模块化、面向对象的特性导致了大量的重复执行,而过程方法通常可以避免这些重复执行。
我并不是要挑c#或。net框架。我也不是说模块化、泛化、库/语言特性、OOP等等都是不好的东西。我曾经用C语言进行大部分开发,后来用c++,最近用c#。类似地,在使用C之前,我主要使用汇编。我的语言每“提高”一步,我就能在更短的时间内写出更好、更可维护、更健壮的程序。然而,它们的执行速度往往要慢一些。
主要的因素是它是一种静态类型的语言,可以编译为机器代码。此外,由于它是一种低级语言,它通常不会做任何您不让它做的事情。
这些是我想到的其他一些因素。
Variables are not automatically initialized No bounds checking on arrays Unchecked pointer manipulation No integer overflow checking Statically-typed variables Function calls are static (unless you use function pointers) Compiler writers have had lots of time to improve the optimizing code. Also, people program in C for the purpose of getting the best performance, so there's pressure to optimize the code. Parts of the language specification are implementation-defined, so compilers are free to do things in the most optimal way
大多数静态类型语言的编译速度可以和C语言一样快,甚至比C语言更快,特别是如果它们可以假设C语言因为指针别名等原因而不能这样做的话。
推荐文章
- 如何找到Java堆大小和内存使用(Linux)?
- 如何在HTML5中改变视频的播放速度?
- 我如何提高ASP。NET MVC应用程序性能?
- C多行宏:do/while(0) vs作用域块
- time_t最终的类型定义是什么?
- 我需要显式处理负数或零时,总和平方数字?
- 列表推导式和函数式函数比for循环更快吗?
- 函数名周围的括号是什么意思?
- 用C语言创建自己的头文件
- 格式化IO函数(*printf / *scanf)中的转换说明符%i和%d之间的区别是什么?
- main()中的Return语句vs exit()
- 如果不是内存地址,C指针到底是什么?
- 我如何在Visual Studio中预处理后看到C/ c++源文件?
- Pandas loc vs iloc vs at vs iat?
- 当WebSockets可用时,为什么要使用AJAX ?