为什么C在嵌入式软件市场占主导地位?[关闭]


14

现在几乎每个人都会说祝福:

性能

好的,C确实可以编写运动代码。但是毕竟还有其他语言可以做到!而且现代编译器的优化功能非常强大。C是否具有其他语言没有的某些优势?还是在该领域根本不需要更灵活的工具?



@Frustrated:是的,但这只是一个例子,大多数构建设备的人都在使用Arduino。
Ed S.



1
@ dan04,在大多数情况下,这实际上不是问题。德州仪器防御系统和电子事业部的6DOF模拟小组在1988年左右进行了一次小实验。在此之前,他们已经在FORTRAN中进行了所有模拟。他们尝试用PASCAL编写一个,以了解它会带来多大的伤害。他们发现PASCAL对他们的性能影响不大,但是可靠性的提高和调试的简便性远远没有弥补。坦率地说,他们发现PASCAL的强类型检查是一件好事。(是的,他们正在做阵列。)
John R. Strohm

Answers:


41

现在几乎每个人都会说祝福:

性能!

这就是其中的一部分;确定性资源的使用在资源有限的设备上很重要,但是还有其他原因。

  1. 直接访问底层硬件API。
  2. 您可以找到适用于这些设备中绝大多数的C编译器。根据我的经验,这对于任何高级语言都是不正确的。
  3. C(运行时和生成的可执行文件)很小。您无需将大量内容加载到系统中即可运行代码。
  4. 硬件API /驱动程序可能会用C或C ++编写。

14
+1编译器的可用性。早在我们用汇编语言编写所有内容时,第一代编译器就是天赐之物。
Christopher Bibbs

8
+1,我认为确定性的资源使用是最重要的原因之一。您没有足够的内存来在洗碗机中进行各种花哨的垃圾收集。
user281377 2011年

4
+1也用于“确定性资源使用”。在许多嵌入式系统上,此要求甚至排除了动态内存分配的使用。许多其他语言严重依赖动态内存分配(甚至C ++的许多有益方面都需要动态内存)。
Michael Burr

2
我还要再加上一个要点,这实际上是社会原因,而不是技术原因-我认为嵌入式软件开发人员比其他开发人员更趋于保守和抵制变更。根据您的观点,这可能是好事或坏事。
Michael Burr

1
作为系统人员,我对大型抽象持怀疑态度。它们很棒,直到它们停止工作或做一些有趣的事情为止,在这种情况下调试起来可能会非常麻烦。在低级系统中,这不是我想要的。
Ed S.

18

C被设计为对CPU建模,因为C被创建为使Unix跨平台可移植,而不仅仅是编写汇编语言。

这意味着对于需要具有非常接近实际CPU的抽象级别的程序的C语言,C程序可以很好地工作,嵌入式硬件就是这种情况。

注意:C是在1970年左右设计的,当时的CPU比较简单。


3
+1:这绝对原因。也许人们试图设计更新的高级语言来捕获现代处理器的功能,但是没有人设计出流行的语言。
肯·布鲁姆

2
@ vines,C是具有大型运行时库的小型语言。所有这些都可以在运行时库中完成。它只是不会自动迁移到标准C库中,因此它是特定于平台的。

3
+1。C是为PDP-7创建的,最初是在PDP-7上使用的,PDP-7最多具有64个18位字的千字。在这种空间中,更多的“现代”语言很难适应。特别是用于编写Unix之类的OS。
greyfade11年

2
@greyfade:并非如此。UNIX起源于PDP-7,但C没有。引用The C编程语言的序言:“ C最初是由Dennis Ritchie为DEC PDP-11上的UNIX操作系统设计并实现的。”
杰里·科芬

1
@vines:虽然考虑直接支持语言中的线程(参见并发C)当然是合理的,但缓存的主要意义在于它可以使程序运行速度更快,而无需程序员或语言方面的任何干预。
杰里·科芬

11

统治的一个原因是它拥有完成任务所需的正确工具。在Java和C / C ++的嵌入式平台中进行开发之后,我可以告诉您C ++的基本方法更为自然。使开发人员避免因为语言水平太高而感到自己跳得太快,这很烦人。一个很好的例子是Java中没有无符号变量。

而且,VM /解释语言的便捷功能通常是不可行的,因此无法实现,例如垃圾回收。


3
“ Java和C / C ++都”-我希望您的意思是“所有三个:Java C和C ++”,因为C和C ++是不同的语言。
2014年

1
@BЈовић:几年后回复,确认是的,我的意思是全部三个。我对这两个定义都非常满意:“用作功能词来表示并强调包含两个或多个事物中的每一个”(两个或多个事物):-)
celebdor

10

C本身仅需要很少的运行时支持,因此开销要低得多。您不必在运行时支持上花费内存或存储,也不需要花费时间/精力来最小化该支持,也不必在项目设计中考虑到这一点。


1
它真的永远不会发生,你需要的功能,而且自己彻底改造呢?例如,使用switches 构建的大型状态机是可怕的,而使用类层次结构构建的相同状态机则很好并且易于维护。
葡萄树

1
@vines-您通常具有一组定义的输入,在交换机上构建的状态机/如果比“幕后”多态调用的魔幻般的提法更清晰,更可记录,则为状态机。
马丁·贝克特

2
@Martin:对于在OO开发方面有少许经验的人来说,多态调用既不是“魔术”也不是“幕后”,而且巨大的switch / if语句更清晰,更可记录的想法似乎是完全荒谬的。
Michael Borgwardt

3
找到pin27变高时会发生什么。选项1,搜索“案例PIN27:”选项2在函子的映射上跟踪迭代器,以发现在运行时分配给引脚27的PIN对象将调用哪个迭代器。许多OO代码的问题在于,读取它的唯一方法是本质上运行它。在没有运行时调试的平台上,甚至在没有控制台的平台上,这都意味着要在纸上或脑海中追踪代码。
马丁·贝克特

2
与本次讨论略有不同,这是有原因的switch,在许多嵌入式应用程序中仍会使用梯形图逻辑(您可以说是甚至更原始的版本)。易于调试,易于验证。
geekosaur 2011年

9

正如在其他答案中提到的那样,C是在1970年代初开发的,以取代小型计算机体系结构上的汇编语言。那时,这些计算机的成本通常为数万美元,其中包括内存和外围设备。

如今,您可以使用单价为4美元或更少的16位嵌入式微控制器,获得相同或更高的计算机功能-包括内置RAM和I / O控制器。32位微控制器的成本可能要高一到两美元。

当我为这些小家伙编程时,这是我90%的时间在不设计他们坐在的板上时所做的事情,我想形象地看到处理器将要做什么。如果我可以在汇编器中编程得足够快,那么我会这样做。

我不需要各种各样的抽象层。我经常通过逐步浏览屏幕上的反汇编程序进行调试。开始使用C编写程序时,这样做要容易得多。


1
对于某些嵌入式应用程序,“多一两个美元”非常重要。没有人会注意到价格对其汽车的影响,但是他们会对他们的恒温器或CD播放器产生影响。
David Thornley

3
@David Thornley,是的,完全同意,这就是为什么我目前同时为不同的客户同时使用8、16和32位micros进行项目的原因。(功耗是使用较小设备的另一个原因。)
tcrosley 2011年

1
价格由处理器成本决定,而不是引脚数。电路板比芯片贵得多。
Yttrill 2011年

7

随着编译器的改进和硬件性能的提高,C ++越来越多地被使用,它并不完全占主导地位。但是,由于某些原因,C仍然很受欢迎。

  1. 广泛的支持。几乎每个芯片供应商都提供ac编译器,任何示例代码和驱动程序都可能用c编写。C ++编译器变得越来越普遍,但对于给定的芯片而言却不是合格的证明,并且它们通常是错误的。您还知道任何嵌入式工程师都可以在c中工作。这是该行业的通用语言。

  2. 性能。是的,你说了。在核心例程仍经常用汇编器编写,或至少参考汇编输出用c优化的环境中,性能仍然是最重要的,永远不要低估它的重要性。通常,嵌入式目标的成本非常低,并且具有很小的内存和很少的干扰。

  3. 尺寸。C ++倾向于更大。当然,使用STL的任何东西都会更大。通常,就程序大小和内存占用而言。

  4. 保守主义。这是一个非常保守的行业。部分原因是失败的成本通常较高,调试通常较难访问,部分原因是无需进行更改。对于小型嵌入式项目,c做得很好。


11
看,这是#3似乎是关于C ++的最普遍的神话之一。为C中的5种不同类型编写一个类型安全的容器,与在5种不同类型上使用单个STL容器相比,至少会造成“膨胀”。C程序员通过在不透明类型(void *)上编写容器来解决此问题。将THAT与STL模板进行比较是一个类别错误。必须承认,尽管这确实是偏爱C的最常见“理由”。
Edward Strange

我完全同意,要在c中复制全部功能,最终会产生与c ++相同的足迹。c的“优势”在于它使您具有选择性。在任何重要的项目中,我都希望使用c ++,但是有时目标硬件被限制在某种程度上不切实际。话虽如此,#1确实是我经验中的主要原因。
卢克·格雷厄姆

6

对于嵌入式系统,重要的是性能。但是,就像您说的那样,为什么使用C而不使用其他性能语言?

到目前为止,很多人都提到了编译器的可用性,但是没有人提到开发人员的可用性。比起OCaml,已经有更多的开发人员知道C。

那是三个大家伙。


6

嵌入式软件有很大的不同。

在桌面应用程序上,抽象和库可为您节省大量开发时间。您可以奢侈地抛出另一个兆字节或千兆字节的RAM或某些2 + GHz 64位CPU内核,而其他人(用户)则为此硬件付费。您可能不知道应用程序将在什么系统上运行。

在嵌入式项目中,资源通常非常有限。在我研究的一个项目(PIC 17X系列处理器)中,硬件具有2Kword的程序存储器,8级(硬件内)堆栈和192字节(<0.2kB)RAM。不同的I / O引脚具有不同的功能,您可以根据需要通过写入硬件寄存器来配置硬件。调试涉及示波器和逻辑分析仪。

在嵌入式中,抽象通常会妨碍您的工作,并且会管理(和花费)您没有的资源。例如,大多数嵌入式系统都没有文件系统。微波炉是嵌入式系统。汽车发动机控制器。一些电动牙刷。一些降噪耳机。

对我而言,开发嵌入式系统的一个非常重要的因素是根据指令,资源,内存和执行时间来了解和控制代码所转换的内容。指令的确切顺序通常控制例如硬件接口波形的时序。

抽象和幕后的“魔术”(例如垃圾收集器)非常适合桌面应用程序。当可以动态分配内存时,垃圾收集器可以节省大量时间来减少内存泄漏。

但是,在实时嵌入式世界中,我们需要知道并控制所需的时间,有时甚至要低至十亿分之一秒,并且不能在出现问题时抛出另外几兆的RAM或更快的CPU。一个简单的例子:通过控制占空比对LED进行软件调光时(CPU仅对LED进行开/关控制),处理器不能关闭并进行100ms的垃圾收集,因为这将明显地显示出来闪烁明亮或熄灭。

一个更假设的示例是直接触发火花塞的发动机控制器。如果该CPU关闭并且进行垃圾收集50ms,则发动机将停顿片刻或在错误的曲轴位置处着火,可能会使发动机失速(通过时)或对其造成机械损坏。您可能会杀死某人。


这与C无关,这是真的,您提到的问题只是GC的行为... C ++没有任何GC,知道什么?我个人使用它,因为的行注释和严格的类型安全=)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.