C++ 适合嵌入式系统吗?

电器工程 微控制器 嵌入式 编程 C++
2022-01-03 22:04:31

一个常见的问题,在这里和其他地方。C++ 适合嵌入式系统吗?

微控制器?实时操作系统?烤面包机?嵌入式电脑?

OOP 在微控制器上有用吗?

C++ 是否将程序员从硬件中移出太远而无法提高效率?

Arduino 的 C++(没有动态内存管理、模板、异常)是否应该被视为“真正的 C++”?

(希望这个 wiki 将成为遏制这场潜在圣战的地方)

4个回答

是的,C++ 在嵌入式系统中仍然有用。正如其他人所说,它仍然取决于系统本身,就像 8 位 uC 在我的书中可能是一个禁忌,即使那里有一个编译器并且有些人这样做(不寒而栗)。即使在 8 位微世界中将其缩小到“C+”之类的东西,使用 C++ 仍然有优势。“C+”是什么意思?我的意思是不要使用 new/delete,避免异常,避免使用继承的虚拟类,可能避免一起继承,非常小心模板,使用内联函数而不是宏,使用const变量而不是#defines.

十多年来,我一直在嵌入式系统中使用 C 和 C++,而我对 C++ 的一些年轻热情肯定已经消退,因为一些现实世界的问题动摇了一个人的天真。我在嵌入式系统中看到了最糟糕的 C++,我想将其称为“在 EE 世界中疯狂的 CS 程序员”。事实上,这是我正在与我的客户合作以改进他们在其他代码库中的一个代码库。

C++ 的危险是因为它是一个非常非常强大的工具,就像一把双刃剑,如果没有对其语言和通用编程本身进行适当的教育和训练,它可能会割断你的胳膊和腿。C更像是一把单刃剑,但仍然一样锋利。使用 C++ 很容易获得非常高级别的抽象并创建从长远来看变得毫无意义的混淆接口,这部分是由于 C++ 在解决具有许多不同语言特性(模板、OOP、过程、 RTTI、OOP+模板、重载、内联)。

我完成了 C++ 大师 Scott Meyers 的两个 4 小时 C++ 嵌入式软件研讨会。他指出了一些我以前从未考虑过的关于模板的事情,以及它们可以在多大程度上帮助创建安全关键代码。它的要点是,在必须满足严格的安全关键代码要求的软件中不能有死代码。模板可以帮助您完成此操作,因为编译器仅在实例化模板时创建它需要的代码。但是,必须更全面地了解如何正确设计这一特性,而这在 C 语言中很难实现,因为链接器并不总是优化死代码。

Scott Meyers 非常支持模板和明智地使用内联,我必须说我仍然对模板的狂热持怀疑态度。我倾向于回避它们,尽管他说它们应该只应用于它们成为最佳工具的地方。他还指出,C++ 为您提供了创建非常好的接口的工具,这些接口易于正确使用,并且难以用错。同样,这是困难的部分。在您知道如何以最有效的方式应用这些功能成为最佳设计解决方案之前,您必须达到一定程度的 C++ 掌握水平。

OOP 也是如此。在嵌入式世界中,您必须熟悉编译器将输出什么样的代码才能知道您是否可以处理运行时多态性的运行时成本。您还需要愿意进行测量,以证明您的设计能够满足您的截止日期要求。那个新的 InterruptManager 类会让我的中断延迟太长吗?还有其他形式的多态性可能更适合您的问题,例如 C 也可以做到的链接时多态性,但 C++ 可以通过Pimpl 设计模式 (Opaque pointer)做到。

我说了这么多,C++ 在嵌入式世界中占有一席之地。你可以随心所欲地讨厌它,但它不会消失。它可以用一种非常有效的方式编写,但学习如何正确地编写它比使用 C 更难。它有时在解决问题和表达更好的接口方面比 C 工作得更好,但同样,你必须教育自己,不要害怕学习。

C++ 绝对适合嵌入式系统。我现在使用是否存在良好的开发工具(或缺乏)作为我是否使用特定微处理器的主要标准。

由于资源成本低而适合在嵌入式系统上使用的 C++ 领域:

  • 良好使用类/结构带来的模块化
  • 如果编译器有效地编译它们方面做得很好。模板是一个很好的工具,可以将算法重用到不同的数据类型。

好的领域:

  • 虚函数——我曾经反对这一点,但资源成本非常小(每个一个 vtable ,而不是每个对象;每个对象一个指向 vtable 的指针;每个虚函数调用一个解引用操作)和这个的巨大优势是它允许您拥有一个包含几种不同类型对象的数组,而不必知道它们是什么类型。我最近使用它来拥有一个对象数组,每个对象代表一个 I2C 设备,每个对象都有单独的方法。

不使用的区域,主要是因为在小型系统上无法接受的运行时开销:

  • 动态内存分配——其他人已经提到了这一点,但使用动态内存分配的另一个重要原因是它代表了时序的不确定性;使用嵌入式系统的许多原因都是为了实时应用。
  • RTTI(运行时类型信息)——内存成本相当大
  • 例外 -绝对禁止,因为执行速度受到影响

是的,C++ 当然适用于嵌入式系统。首先让我们澄清一些关于 C 和 C++ 之间区别的误解:

在嵌入式微系统中,如果您担心时间或空间限制,您总是需要谨慎使用高级语言。例如,许多 MCU 不能很好地处理指针,因此在使用堆栈时效率非常低。这意味着您必须小心将变量传递给函数、使用数组和指针以及递归。一个简单的 C 行,例如:

a[i] = b[j] * c[k];

根据这些变量的性质,可以生成大约 4 页的指令。

每当您使用任何高级语言并且担心时间和空间限制时,您都需要知道该语言的每个功能如何转换为您的 MCU 上的机器指令(至少,您使用的每个功能)。这适用于 C、C++、Ada 等等。可能所有语言都包含在小型 MCU 上无法有效翻译的功能。始终检查反汇编列表以确保编译器不会为琐碎的事情生成大量指令。

C语言适合嵌入式MCU吗?是的,只要您密切关注生成的代码。
C++ 适合嵌入式 MCU 吗?是的,只要您密切关注生成的代码。

这就是为什么我认为即使在 8 位 MCU 上 C++ 也比 C 更好的原因:C++ 提供了改进的支持:

  • 数据隐藏
  • 更强的打字/检查
  • 使用类的多外设透明度
  • 模板(如往常一样,如果小心使用)
  • 初始化列表
  • 常量

这些特征都没有比 C 的典型特征重。

当您升级到 16 位或 32 位 MCU 时,使用 C 的较重功能(堆栈、堆、指针、数组、printf 等)开始变得有意义。同样,在更强大的 MCU 上变得合适使用 C++ 的较重特性(堆栈、堆、引用、STL、新建/删除)。

因此,无需为 PIC16 上的 C++ 的想法而战栗。如果您正确了解您的语言和您的 MCU,那么您将知道如何同时有效地使用它们。

我总是觉得这些辩论读起来很有趣。与其说是关于各种可用语言的优缺点的智力讨论,不如说是因为您通常可以根据某人的工作/经验/感兴趣的领域来确定某人对该主题的立场。就在那里,“过早优化”的论点是 CS 专业和维护程序员左右引用 Knuth 的话,而那些在现实世界中工作的人认为他们都疯了(我是后者的成员)公平起见)。

归根结底,您可以使用 C 或 C++ 开发出色的软件或在此处插入语言它归结为开发人员的能力而不是语言。通常只有在您选择了错误的语言开始并且现在需要将其扭曲以解决您的问题时才需要成为语言专家,在大多数情况下,这些是您需要深入研究晦涩的功能或编译器的唯一情况实现目标的技巧。

我经常听到人们以“我是语言 X 方面的专家”来开始这些论点,老实说,我立即抹黑这些人,因为在我看来,他们已经从错误的角度解决了问题,之后的一切都被污染了他们希望使用他们的工具来解决问题并展示它是多么“酷”。

我经常看到开发人员首先选择一个工具集,然后再尝试将其弯曲到他们的问题上,这是完全错误的,并且会导致糟糕的解决方案。

正如我在对另一个答案的评论中提到的那样,这些语言战争经常演变成争论语言 X 允许程序员做更多愚蠢的事情。虽然读起来很有趣,但所有这些陈述的真正意思是,您在雇用优秀的开发人员时遇到了问题,需要直接解决这个问题,而不是试图通过继续雇用糟糕的开发人员并选择工具让他们做的事情尽可能少来解决这个问题尽可能的损坏。

在我看来,优秀的开发人员,无论是软件开发还是硬件开发,都要研究问题、构建解决方案并找到允许他们以“最佳方式”表达解决方案的工具。所需工具是否是您以前从未使用过的东西并不重要,在您为项目使用 3-4 种语言/开发工具之后,选择新的工具应该对您的开发时间影响最小。

当然,“最佳方式”是一个主观术语,也需要在研究阶段进行定义。需要根据手头的问题考虑许多问题:性能、易于表达、代码密度等。我没有在该列表中包含可维护性是有原因的,我不在乎您选择哪种语言,如果您选择了合适的工具并花时间理解应该“免费”出现的问题。难以维护的代码通常是由于选择了错误的工具或糟糕的系统结构,这导致了一个丑陋的乱七八糟的乱七八糟的东西才能让它工作。

声称任何一种语言都比任何其他语言“更好”是愚蠢的,而没有定义一个特定的感兴趣的问题。面向对象的方法并不总是比函数式方法好。有一些问题非常适合面向对象的设计范式。有很多没有。同样的说法也适用于人们似乎喜欢强调的许多语言特征。

如果您将超过 20% 的时间花在实际键入代码的问题上,那么您可能正在开发一个非常糟糕的系统,或者拥有非常糟糕的开发人员(或者您仍在学习)。您应该将大部分时间花在预先绘制问题图表并确定应用程序的各个部分如何交互。将一群才华横溢的开发人员放在一个有标记板和要解决的问题的房间里,并告诉他们在他们对整个系统感到满意之前不允许编写任何代码或选择任何工具,这将有助于提高质量输出和速度开发比选择任何热门的新工具都可以保证缩短开发时间。(查找 scrum 开发作为与我的论点截然相反的参考)

通常不幸的现实是,许多企业只能通过编写的行数或看到“有形输出”来衡量开发人员的价值。他们认为在有记号板的房间里呆上 3 周是生产力的损失。开发人员经常被迫加快开发的“思想”阶段,或者由于公司内部的一些政治问题而被迫使用工具集,“我老板的兄弟在 IBM 工作,所以我们只能使用他们的工具”,那种垃圾. 或者更糟的是,你从公司那里得到一组不断变化的需求,因为他们没有能力进行适当的市场研究,或者不了解变化对开发周期的影响。

抱歉,我对这个话题有点偏离主题,我对这个话题有相当强烈的看法。