深度嵌入式系统通常在C语言中实现。为什么会这样?这样的系统是否也能从C++中获益?嵌入式开发人员在将广泛、高效的深度嵌入式代码库从C转换为C++方面的实践经验的贡献。
嵌入式和深度嵌入式系统通常用C而不是C++实现。软件开发人员必须放弃C++作为强类型系统、模板元编程(TMP)和面向对象编程(OOP)的优势。C++不用于嵌入式系统,因为嵌入式系统中的编译器通常不支持较新版本的C++标准。另一个原因是对如何在这方面使用C++的知识不足,以及与C相比C++总是开销较大的神话。
你可以使用C++吗?
也许也没有编译器对你需要使用的目标系统提供足够的C++支持。至少对于基于武器的系统来说,情况已经有了很大改善。例如,它基于Clang/LLVM,这是Arm版本6的编译器工具链,因此支持C++14以及未来C++标准的更新版本。
嵌入式开发人员的经验和开销测量基于此工具链的使用。我们的应用程序(根据IEC 62304开发助听器固件)在具有以下功能的ASIC上运行:Arm Cortex-M0 CPU,128 KB ROM和144 KB RAM。
为什么使用C++?
许多C开发人员想知道为什么他们应该在嵌入式系统中使用C++。这是因为他们可以从面向对象编程(OOP)中获益。许多C代码库已经在尝试“伪造”OOP:使用包含“类成员”的结构,使用假装为“成员函数”的函数(指针指向该结构作为第一个参数)。如果你在C++中正确使用基本OOP方法,这将为你带来更多好处:
l 更易于应用语法
l 编译器检查的变量/函数的公共/私有声明
l 使用构造函数/析构函数控制成员变量的初始化/销毁
更复杂的OOP概念(带有虚拟函数),如继承和多态性,也很难在C中维护。
嵌入式开发人员使用C++的另一个优点是支持编译时的优化,例如模板元编程(TMP),以及编译时对constexpr函数的求值。即使是最简单的应用程序也为我们提供了以下优势:
l C宏“常量”可以用正确类型的constexpr变量替换;
l C宏“函数”可以替换为模板函数,这增加了类型安全性;此外,相同的函数定义不仅可以在编译时使用,必要时也可以在运行时使用;
l 与常规C枚举相比,作用域枚举(枚举类)提供了额外的类型安全性;
l 类型转换(在嵌入式系统中通常不可避免)可以隐藏在一个受控的、小型的类型安全模板实用程序函数库后面。因此,(非库)嵌入应用程序代码中禁止所有类型转换。
模板也可用于优化代码大小。如果嵌入式开发人员用C语言实现,代码的可维护性就会降低。
C++用于混合内存系统
在具有混合存储器架构(例如ROM/RAM/NVM)的系统中,C++可用于ROM修补。例如,你有一个MyLibClass类,它被编译并存储在ROM中。然后你有一个MyUserClass类,它使用MyLibClass并从RAM运行,例如在引导期间从NVM加载之后。在取出ROM或甚至发布基于该ROM的产品后,你将发现MyLibClass中的一个错误,你希望为你的产品修复(即补丁)。
如果MyLibClass中的函数是虚拟的,这是可能的。然后,可以从MyLibClass类派生MyLibClassPatched类并覆盖错误函数。MyLibClassPatched必须放在RAM中(因为ROM不能再更改)。现在嵌入式开发人员只需在MyUserClass中将MyLibClass更改为MyLibClassPatched。这修复了错误,无需在RAM中重新实现整个MyLibClass。