一个普遍的问题,在这里和其他地方。C ++是否适合嵌入式系统?
微控制器?实时操作系统?烤面包机?嵌入式PC?
OOP在微控制器上有用吗?
C ++是否会将程序员从硬件中移走太远以至于效率不高?
Arduino的C ++(没有动态内存管理,模板,异常)是否应被视为“真正的C ++”?
(希望这个Wiki将成为包含这场潜在的圣战的地方)
一个普遍的问题,在这里和其他地方。C ++是否适合嵌入式系统?
微控制器?实时操作系统?烤面包机?嵌入式PC?
OOP在微控制器上有用吗?
C ++是否会将程序员从硬件中移走太远以至于效率不高?
Arduino的C ++(没有动态内存管理,模板,异常)是否应被视为“真正的C ++”?
(希望这个Wiki将成为包含这场潜在的圣战的地方)
Answers:
是的,C ++在嵌入式系统中仍然有用。就像其他人所说的那样,它仍然取决于系统本身,就像8位uC在我的书中可能是不行的,即使那里有编译器并且有人这样做(颤抖)。即使在8位微型环境中,即使将C ++缩减为“ C +”之类的东西,使用C ++仍然有一个优势。我所说的“ C +”是什么意思?我的意思是不要使用new / delete,避免异常,避免具有继承的虚拟类,可能一起避免继承,使用模板时要非常小心,使用内联函数而不是宏以及使用const
变量来代替#defines
。
我从事嵌入式系统的C和C ++工作已有十多年了,由于一些现实世界的问题动摇了我的天真,我对C ++的年轻热情肯定已经减弱。我已经看到了嵌入式系统中最糟糕的C ++,我将其称为“ CS程序员在EE世界中疯狂”。实际上,这就是我正在与客户合作以改善他们拥有的这一代码库的东西。
C ++的危险在于,它是一个非常强大的工具,就像一把两刃剑,如果不正确地接受其语言和通用编程本身的教育和训练,就会割伤您的胳膊和腿。C更像是单刃剑,但仍然一样锋利。使用C ++,很容易获得非常高级的抽象并创建混淆的接口,这些接口从长远来看变得毫无意义,这在一定程度上是由于C ++能够灵活地解决具有许多不同语言功能(模板,OOP,程序, RTTI,OOP +模板,重载,内联)。
我完成了由C ++专家Scott Meyers进行的两个4小时的有关C ++嵌入式软件的研讨会。他指出了一些我从未考虑过的关于模板的东西,它们还可以帮助创建安全关键代码。关键是,您不能在必须满足严格的安全关键代码要求的软件中包含无效代码。模板可以帮助您完成此任务,因为编译器仅在实例化模板时创建所需的代码。但是,必须对使用它们进行更彻底的教育,以便正确地为此功能设计,这在C语言中很难完成,因为链接器并不总是优化死代码。
Scott Meyers在模板和明智地使用内联方面非常支持,我必须说,我仍然对模板感兴趣。我倾向于避开它们,即使他说只应将它们应用到成为最佳工具的地方。他还指出,C ++为您提供了制作非常好的接口的工具,这些接口易于正确使用,而难以错误使用。同样,这是困难的部分。在您知道如何以最有效的方式应用这些功能成为最佳设计解决方案之前,必须先熟练掌握C ++。
OOP也是如此。在嵌入式世界中,您必须熟悉编译器将要吐出的哪种代码,才能知道您是否可以处理运行时多态性的运行时成本。您还需要愿意进行测量,以证明您的设计将满足您的最后期限要求。新的InterruptManager类会使我的中断等待时间太长吗?还有其他形式的多态可以更好地解决您的问题,例如C可以做到的链接时多态,但是C ++可以通过Pimpl设计模式(不透明指针)来实现。
我要说的就是C ++在嵌入式世界中占有一席之地。您可以恨自己想要的一切,但它不会消失。可以用非常有效的方式编写它,但是要比使用C来学习正确的方法要困难得多。在解决问题和表达更好的接口方面,有时它可以比C更好地工作,但是同样,您必须教育自己,不要害怕学习方法。
C ++绝对适用于嵌入式系统。现在,我将是否存在良好的开发工具(或缺乏)作为我是否使用特定微处理器的主要标准。
可以在嵌入式系统上很好使用的C ++区域,因为它们的资源成本低:
可以的区域:
不使用的区域,主要是因为小型系统无法接受的运行时开销:
foo
调用,并创建了一些对象并进行了调用,从而引发了异常,则系统必须以某种方式为创建的对象调用析构函数,然后再将控制返回给。除非将异常完全禁用,否则将无法知道是否会抛出异常,因此必须包括额外的代码以允许这种可能性。我希望看到带有“检查的异常”的C ++变体来解决这个问题;如果例程可以允许异常逃逸……bar
try
catch
bar
boz
bar
foo
bar
boz
add r15,r14,#2
而不是mov r15,r14
; 正常退出;通过异常退出ldrhs r0,[r14] / add r15,r14,r0
。正常退出的周期成本为零,并且没有堆栈帧限制。
是的,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,那么您将知道如何一起有效地使用它们。
a[i] = b[j] * c[k];
根据这些变量的性质,可以生成大约4页的指令。” 如果您的MCU /编译器这样做,是因为您使用的是80年代的车库业余CPU。
我总是觉得阅读这些辩论很有趣。关于各种可用语言的优缺点的学术讨论并没有那么多,而是因为您通常可以根据某人的工作/经验/兴趣领域来确定某人对该主题的立场。就在那儿,带有“过早优化”的论点是CS专业和维护程序员左右引用Knuth,以及那些在现实世界中工作的人,他们认为性能太疯狂了(我是后者的成员)公平起见)。
最终,您可以使用C或C ++开发出色的软件,或在此处插入语言。它取决于开发人员的能力,而不是语言。通常,只有当您选择了错误的语言并且现在需要将其转换为解决问题时,才需要成为语言专家,在大多数情况下,这是唯一需要深入了解晦涩功能或编译器的情况实现目标的技巧。
我经常听到人们以“我是X语言专家等等”开始争论,说实话,我立即抹黑了这些人,因为在我看来,他们已经从错误的角度解决了问题,此后的一切都被污染了。他们渴望使用他们的工具来解决问题,并表明它有多“酷”。
我经常看到开发人员首先选择工具集,然后再尝试解决其问题,这是完全错误的,并导致了解决方案。
正如我在对另一个答案的评论中提到的那样,这些语言之争常常演变成争论:语言X允许程序员做更多愚蠢的事情。在娱乐阅读的同时,所有这些陈述实际上意味着您在雇用优秀的开发人员时遇到了问题,需要直接解决该问题,而不是通过继续雇用不良的开发人员并选择使他们做的事少的工具来试图解决问题。尽可能的损坏。
我认为优秀的开发人员,无论是软件开发还是硬件开发,都要研究问题,设计解决方案并找到使他们能够以“最佳方式”表达解决方案的工具。使用了3-4种语言/开发工具进行项目选择新工具后,所需的工具是否是您以前从未使用过的工具并不重要。
当然,“最佳方法”是一个主观术语,还需要在研究阶段进行定义。一个人需要根据眼前的问题考虑许多问题:性能,表达的难易程度,代码密度等。我之所以没有将可维护性列入该列表是有原因的,我不在乎您选择哪种语言,如果您选择了合适的工具并花时间来理解应该免费的问题。难以维护代码通常是由于选择了错误的工具或较差的系统结构而导致的,这导致难看的杂乱无章的混乱使其无法正常工作。
声称任何一种语言都比其他任何一种都“好”,而没有定义一个特定的问题。面向对象的方法并不总是比功能方法更好。有一些问题非常适合面向对象的设计范例。有很多没有。关于人们似乎喜欢使用的许多语言功能,可以做出相同的陈述。
如果您花费超过20%的时间在实际键入代码的问题上,则可能是您生产的系统很差,或者开发人员的能力很差(或者您还在学习)。您应该将大部分时间花在解决问题并确定应用程序各部分之间的交互方式上。将一群才华横溢的开发人员放在一个带有标记板和问题的房间中,并告诉他们除非他们对整个系统感到满意,否则他们不能编写任何代码或选择任何工具,这将大大提高系统的质量。输出和加快开发速度,而不是选择任何热门的新工具都可以保证缩短开发时间。(将scrum开发作为与我的论点相反的参考)
通常,不幸的现实是,许多企业只能通过编写的行数或看到“有形的输出”来衡量开发人员的价值。他们将在带有标记板的房间中的3周视为生产力的损失。开发人员经常被迫加速开发的“思考”阶段,或者被迫使用公司内部某个政治问题所设定的工具,“我老板的兄弟为IBM工作,所以我们只能使用他们的工具”,这种垃圾。或更糟糕的是,您会从公司那里收到一组不断变化的需求,因为它们无法进行适当的市场研究或不了解更改对开发周期的影响。
抱歉,这个话题有点偏离主题,我对此主题有很强的见解。
任何语言都适用于嵌入式系统。嵌入式仅表示:与免费计算机相反,是较大设备的一部分。
当要求使用(硬)实时或资源有限的系统时,该问题具有更大的相关性。
对于实时系统,C ++是在对严格的时间限制进行编程时仍然适合的最高语言之一。除了堆使用(免费运算符)外,它没有不确定的执行时间的构造,因此您可以测试程序是否满足其计时要求,并且有更多的经验甚至可以预测它。当然,应该避免使用堆,尽管新的运算符仍然可以用于一次性分配。C ++通过C提供的结构可以在嵌入式系统中得到很好的利用:OO,异常,模板。
对于资源非常有限的系统(8位芯片,RAM不足几Kb,没有必需的堆栈),尽管可能仍被用作“更好的C”,但完整的C ++可能不合适。
我认为不幸的是,Ada似乎仅在某些壁ni中使用。从很多方面来说,它都是Pascal ++,但是没有与一开始就已经很混乱的语言向上兼容的负担。(编辑:严重的混乱当然是C。帕斯卡是一门美丽但有些不切实际的语言。)
================================================== ==============
编辑:我正在键入一个新问题的答案(“在什么情况下,当我们对微控制器进行编程时,C ++是必需的吗?”),因此我将添加我写的内容:
使用任何编程语言从来没有一个绝对的理由,但是在特定情况下,可能存在具有或多或少影响的参数。在很多地方都可以找到有关此问题的讨论,其职位范围从“从不使用C ++用于微控制器”到“始终使用C ++”。我更喜欢最后一个职位。我可以提出一些论点,但您必须自己决定它们在特定情况下(以及在哪个方向)承担的重量。
我的博客上有一些关于在小型系统(即微控制器)上使用C ++的著作。
以我的经验,C ++通常不适用于小型嵌入式系统。我的意思是微控制器和无操作系统的设备。
许多C ++ OOP技术都依赖于动态内存分配。在小型系统中通常不存在这种情况。
STL和Boost确实展示了C ++的强大功能,两者的足迹都很大。
C ++鼓励程序员抽象化机器,而在受限的系统中必须将其包含在内。
去年,我将商业远程桌面产品移植到了手机上。它是用C ++编写的,并且可以在Windows,Linux和OSX上运行。但是,它严重依赖STL,动态内存和C ++异常。要使其在WinCE,Symbian和无操作系统环境中运行,最明智的选择是C重写。
我希望在有关裸机和资源受限系统上的C ++的讨论中增加更多的热量。
C ++中的问题:
异常尤其是一个RAM问题,因为所需的“紧急缓冲区”(例如,内存不足异常就在其中)可能大于可用的RAM,并且肯定对微控制器造成浪费。有关更多信息,请参见n4049和n4234。应该将它们关闭(这是当前未指定的行为,因此请确保不要抛出)。第14研究组目前正在研究更好的方法。
RTTI可能永远都不值得开销,应该将其关闭
大型调试版本,尽管在经典台式机开发中这不是问题,但如果调试不适合芯片,则可能是一个问题。问题来自于为清晰起见而添加的模板代码或额外的函数调用。这些额外的函数调用将被优化器再次删除,并且增加的清晰度或灵活性可能是一个很大的优势,但是在调试版本中,这可能是个问题。
堆分配。尽管STL允许使用自定义分配器,但对于大多数程序员而言,这可能很复杂。堆分配是不确定的(即,不是实时的),即使进行了测试,碎片也会导致意外的内存不足情况发生。为了跟踪自由空间和变化的大小,堆所需的簿记可能是小对象的问题。通常最好使用池分配(在C和C ++中都是这样),但是对于只使用堆的C ++程序员来说,这可能是异常的。
运行时多态和其他间接调用通常会对性能造成很大的影响,问题通常出在更多地方,因为优化器无法比实际获取和跳转到该地址看到更多内容。因此,在C和C ++中应避免进行间接调用,因为在C和C ++中,它们在文化中更加根深蒂固(并且在其他领域中非常有用)。
与clib的隐式接口可能会出现问题。clib问题在C ++类别中可能是违反直觉的,但问题是由并发环境中的资源隐式共享引起的(在C中共享更明确)。通用newLib实现的使用通常会导致很多膨胀,这在uC中通常是不需要的,另一方面,newLibNanno并不是可重入的,因此必须序列化对其的访问(此处过于简化)。对于C来说也是一个问题,但是访问更明确。根据经验,除非您确定它不会以某种方式访问clib中的状态(例如,errorno或堆),否则基本上不应在ISR上下文中使用命名空间std中的任何内容。如果您使用线程(我更喜欢RTC)来覆盖new和delete以同步对malloc和free的访问,这也很重要。
总之,C ++存在一些问题,但它们基本上都是可修复的或可避免的。
现在对于C,这里的问题是高阶。我没有C语言的语法能力来抽象事物,而我无法在编译时执行优化或检查不变式。因此,我无法以某种方式正确地封装事物,即用户不需要知道它们的工作方式就可以使用它们,而我的大部分错误检测都是在运行时完成的(这不仅太迟,而且还会增加成本)。本质上,在C语言中通用的唯一方法是通过数据,我将格式字符串传递给printf或scanf,例如在运行时对其进行评估。然后,对于编译器而言,很难证明我没有使用某些选项,这些选项在传递正确的数据时理论上是可行的,这意味着潜在的死代码生成和优化潜力的损失。
我知道我可能会在这里发疯,但是我在32位微控制器上的经验是,在专家之间(如在C ++中可能是高度模板化的)编写的C和C ++的比较中,C ++是一种效率更高的语言。任何东西都必须是通用的(就像在任何库中一样),并且在非通用情况下它们基本上是等效的。对于新手来说,利用C ++中的专家库实现者的专业知识也更加容易。
同时,实际上只有很少的函数无法传递不正确的数据,只要输入不是int而是something
我恰巧使用int作为表示方法的函数,那么就有可能获得它错误(传递无效值或“ otherThing”而不是“ something”)。在C语言中,检查用户是否输入错误的唯一方法是在运行时。在C ++中,我可以执行一些检查,而不是全部检查,但可以在编译时执行一些免费的检查。
归根结底,C团队通常与其最弱的程序员一样强大,并且由此产生的代码好处是多人游戏1或性能损失。我的意思是,在一个独特的设计决策独特的环境中,它要么只执行一项工作,要么仅执行一项唯一的工作,要么具有足够的通用性,就可以在多种环境中使用(其他微控制器,其他内存管理策略,其他延迟与性能)。吞吐量的取舍等),但具有固有的性能成本。
在C ++中,事物可以由专家进行封装,并在许多环境中使用,在这些环境中,编译时代码生成可适应特定任务,而静态检查可防止用户以零成本进行愚蠢的工作。在这里,我们在通用和快速之间的权衡要少得多,因此最终从成本与收益的角度来看,是一种性能更高,更安全和更具生产力的语言。
很好的批评是,仍然缺少用于嵌入式的良好C ++库,这可能会导致务实的决定,即在C ++编译器上主要使用C。在项目中仅使用C的决定本质上是出于意识形态的驱动,出于对遗留支持的需求,或者承认团队的纪律性不足以避免选择C ++而不是C可以完成的一系列愚蠢的选择。同时要有足够的纪律性,以至于不能做任何愚蠢的事情,而这在C语言中是无法防范的,而在C ++中是可以避免的。
我的背景: 刚从贝尔实验室老程序员的学校培训结束;已经工作了3年,其中2个是本科生研究项目;VB.NET中的数据采集/过程控制。用了1.5年的时间在VB6中的企业数据库应用程序上工作。目前正在为具有2GB存储,512MB RAM,500MHz x86 CPU的嵌入式 PC 进行项目;使用C ++同时运行的几个应用程序,中间之间具有IPC机制。是的,我还年轻。
我的看法:在上述环境下, 我认为C ++可以有效地工作。诚然,硬实时性能不是我正在使用的应用程序的要求,在某些嵌入式应用程序中,这可能是个问题。但是,这是我学到的东西:
C ++从根本上不同于C(即,没有C / C ++)。尽管所有有效的C语言都是有效的C ++语言,但C ++语言却是一种截然不同的语言,需要学习如何使用C ++(而不是C)进行编程,以便在任何情况下都可以有效地使用它。在C ++中,您需要面向对象的程序,而不是过程式的程序,而不是两者的混合(大型类具有很多功能)。通常,您应该集中精力制作具有很少功能的小型类,并将所有小型类组合为一个更大的解决方案。我的一位同事向我解释说,我以前是在对象上进行过程编程的,这很麻烦,而且很难维护。当我开始应用更多的面向对象技术时,我发现代码的可维护性/可读性得到了提高。
C ++以面向对象开发的形式提供了其他功能,这些功能可以提供一种简化代码以使其更易于阅读/维护的方式。老实说,我认为在进行OOP时不会在性能/空间效率方面有所改进。但是我认为OOP是一种可以帮助将复杂问题分解为许多小片段的技术。这对从事代码工作的人员很有帮助,这一过程中的要素不容忽视。
反对C ++的许多论点主要与动态内存分配有关。C也有同样的问题。您可以编写面向对象的应用程序而无需使用动态内存,尽管使用对象的好处之一是可以轻松地动态分配这些内容。就像在C语言中一样,您必须小心如何管理数据以减少内存泄漏,但是RAII技术在C ++中使这一过程变得更加简单(通过将动态内存封装在对象中来自动破坏动态内存)。在某些应用程序中,每个内存位置都很重要,这可能太繁琐而难以管理。
编辑:
是的,C ++的问题在于代码占用量的增加。
在某些系统中,您需要计算字节数,在这种情况下,您将不得不接受接近系统界限的运行成本,这是C语言增加的开发成本。
但是,即使在C语言中,对于一个设计良好的系统,您也需要将所有内容封装起来。设计良好的系统很难,而C ++为程序员提供了一种结构化和受控的开发方法的场所。学习OOP是有成本的,如果您要切换到OOP,则您会接受它,并且在许多情况下,管理层宁愿继续使用C而不支付费用,因为很难衡量要转换的结果。提高生产力。您可以在这里看到嵌入式系统专家Jack Ganssle的文章。
动态内存管理是魔鬼。并非如此,魔鬼是自动路由,动态内存管理在PC上运行良好,但是您可以期望至少每隔几周重新启动PC。您会发现,随着嵌入式系统继续运行5年,动态内存管理可能会真正陷入困境并开始出现故障。Ganssle在他的文章中讨论了堆栈和堆之类的问题。
C ++中的某些事情更容易引起问题并占用大量资源,删除动态内存管理和模板是使C ++的足迹更接近C足迹的重要步骤。这仍然是C ++,您不需要动态内存管理或编写好的C ++模板。我没有意识到它们删除了异常,我认为异常是我在发行版中删除的代码的重要组成部分,但直到那时才使用。在现场测试中,我可以让异常生成消息来通知我异常被捕获。
我认为Linus Torvalds的这种反C ++声音很有趣。
C ++绝对最糟糕的功能之一是它如何使很多事情与上下文相关,这仅意味着当您查看代码时,局部视图很少会提供足够的上下文来了解正在发生的事情。
他不是在谈论嵌入式系统领域,而是在谈论Linux内核开发。对我而言,相关性来自于此:C ++需要理解更大的上下文,并且我可以学习使用一组对象模板,我不相信自己会在几个月后必须更新代码时记住它们。
(另一方面,我目前正在使用Python(不是C ++,但使用相同的OOP范例)在嵌入式设备上进行工作,这将确实存在该问题。在我的辩护中,这是一个功能强大的嵌入式系统,可以称为PC 10年前。)
我认为其他答案对于正反两方面和决策因素都有很好的论据,所以我只想总结一下并添加一些评论。
对于小型微控制器(8位),没有办法。您只是要伤害自己,没有收获,您将浪费太多资源。
对于具有不错操作系统的高端微控制器(例如32位,10或100 MB的MB用于内存和存储),这是完全可以的,而且我敢说,甚至推荐使用。
所以问题是:边界在哪里?
我不确定,但是一旦我用C ++开发了一个具有1 MB RAM和1 MB存储空间的16位uC系统,便后悔了。是的,它确实有效,但是我所付出的额外工作并不值得。我必须使它适应,确保诸如异常之类的东西不会产生泄漏(OS + RTL支持非常错误且不可靠)。而且,OO应用程序通常会做很多小的分配,而这些应用程序的堆开销又是另一个噩梦。
有了这些经验,我会为以后的项目假设我只会在至少16位,RAM和存储空间至少为16 MB的系统中选择C ++。这是一个任意限制,并且可能会根据应用程序类型,编码样式和习惯用法等因素而有所不同。但是,请注意,我建议使用类似的方法。
C ++的某些功能在嵌入式系统中很有用。还有其他一些东西,例如例外情况,可能会很昂贵,而且其代价可能并不总是显而易见的。
如果我有德鲁特,那将是一种流行的语言,它结合了两种语言的优点,并包含了两种语言所缺乏的一些功能;一些供应商提供了一些这样的功能,但是没有标准。我想看几件事:
内联void copy_uint32s(uint32_t * dest,const uint32_t * src,__ is_const int n) { 如果(n <= 0)返回; 否则,如果(n == 1){dest [0] = src [0];} 否则(n == 2){dest [0] = src [0]; dest [1] = src [1];} 否则,如果(n == 3){dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2];} 否则,如果(n == 4){dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2]; dest [3] = src [3];} 否则memcpy((void *)dest,(const void *)src,n * sizeof(* src)); }如果可以在编译时评估“ n”,那么上面的代码将比对memcpy的调用更有效,但是如果不能在编译时评估“ n”,则生成的代码将比简单地执行的代码更大,更慢。叫做memcpy。
我知道C ++之父不太热衷于仅嵌入式版本的C ++,但我认为与仅使用C相比,它可以提供一些相当大的改进。
有人知道是否正在针对任何类型的标准考虑上述内容吗?
C ++不仅仅是一种编程语言:
a)是一种“更好的” C b)是一种面向对象的语言c)这是一种允许我们编写通用程序的语言
尽管所有这些功能都可以单独使用,但是同时使用其中三个功能可以达到最佳效果。但是,如果您只选择其中之一,嵌入式软件的质量将会提高。
a)是“更好”的C
C ++是一种强大的类型化语言。比C强。您的程序将受益于此功能。
有些人害怕指针。C ++包括参考。重载功能。
值得一提:较大或较慢的程序都不会产生这些功能。
b)这是一种面向对象的语言
有人在这篇文章中说,在微控制器中抽象机器不是一个好主意。错误!我们所有人,嵌入式工程师,总是将计算机抽象化,只是带有C ++的其他语法。我看到的这个问题是,有些程序员不习惯于在对象中思考,这就是他们看不到OOP的好处。
每当您准备使用微控制器的外设时,很可能已经以设备驱动程序的形式(从您本人或第三方)为我们抽象了该外设。如我之前所说,该驱动程序使用C语法,如以下示例所示(直接取自NXP LPC1114示例):
/ *在TICKRATE_HZ设置计时器以进行匹配和中断* /
Chip_TIMER_Reset(LPC_TIMER32_0);
Chip_TIMER_MatchEnableInt(LPC_TIMER32_0,1);
Chip_TIMER_SetMatch(LPC_TIMER32_0,1,(timerFreq / TICKRATE_HZ2));
Chip_TIMER_ResetOnMatchEnable(LPC_TIMER32_0,1);
Chip_TIMER_Enable(LPC_TIMER32_0);
您看到抽象了吗?因此,当出于相同目的使用C ++时,通过C ++的抽象和封装机制可以将抽象提升到一个新的水平,而成本却为零!
c)这是一种允许我们编写通用程序的语言
通用程序是通过模板实现的,并且模板对于我们的程序也没有任何费用。
此外,静态多态性是通过模板实现的。
虚拟方法,RTTI和异常。
使用虚拟方法时存在一个折衷:更好的软件与性能的损失。但是,请记住,动态绑定可能使用虚拟表(函数指针数组)来实现。我已经在C中做了很多次(甚至是定期进行),所以我看不到使用虚拟方法的弊端。而且,C ++中的虚拟方法更加优雅。
最后,关于RTTI和异常的建议:不要在嵌入式系统中使用它们。不惜一切代价避免它们!
我的背景是实时的(嵌入式,MCU,PC,Unix,其他)。安全至关重要。我向STL介绍了以前的雇主。我不再这样做了。
一些火焰含量
C ++是否适合嵌入式系统?
嗯 C ++是编写的痛苦,也是维护的痛苦。C +还可以(不要使用某些功能)
微控制器中的C ++?实时操作系统?烤面包机?嵌入式PC?
我再次说梅。C +并不太糟糕,但是ADA却不那么痛苦(这实际上是在说些什么)。如果像我这样幸运的话,您可以使用嵌入式Java。检查数组访问,并且没有指针算法,因此代码非常可靠。嵌入式Java中的垃圾收集器并不是最高优先级,并且具有一定范围的内存和对象重用,因此,设计良好的代码可以在没有GC的情况下永久运行。
OOP在微控制器上有用吗?
当然可以 UART是一个对象..... DMAC是一个对象...
对象状态机非常简单。
C ++是否会将程序员从硬件中移走太远以至于效率不高?
除非它是PDP-11,否则就不是您的CPU。C ++最初是C语言的预处理器,因此Bjarne Stroustrup不会因为在AT&T上进行缓慢的Simula仿真而被嘲笑。C ++不是您的CPU。
去获得一个运行Java字节码的MCU。Java程序。嘲笑C家伙。
Arduino的C ++(没有动态内存管理,模板,异常)是否应被视为“真正的C ++”?
不。就像所有针对MCU的混蛋C编译器一样。
第四,嵌入式Java或嵌入式ADA已标准化。其他一切都是悲伤。
嵌入式系统旨在执行某些特定任务,而不是用作执行多个任务的通用计算机。嵌入式系统是计算机硬件和软件的组合。C是所有现代语言的母亲。这是一个较低级别的语言,但功能全面,并且可以处理所有类型的硬件。因此,C / C ++是开发嵌入式系统软件的最佳选择,它非常适合每个嵌入式系统。众所周知,C是一种开发语言。操作系统UNIX是用C编写的。由于成功的软件开发经常是为给定的项目选择最佳语言,因此令人惊讶地发现C / C ++语言已证明自己适用于8位和64位处理器; 在具有字节,千字节和兆字节内存的系统中。C具有处理器独立性的优势,这使程序员可以专注于算法和应用程序,而不是特定处理器体系结构的细节。但是,这些优点中的许多优点同样适用于其他高级语言。但是C / C ++成功了,而其他许多语言却大都失败了?
<rant>
我认为C ++首先是一种糟糕的语言。如果要使用OOP,请编写Java程序。C ++不会执行OOP范例,因为直接内存访问完全在(滥用)能力范围内。
如果您有MCU,那么您所谈论的闪存很可能少于100kB。您想使用一种对内存的抽象为的语言进行编程:当我声明一个变量或数组时,它获取内存,句点;除非在极少数情况下在程序启动期间进行一次调用,否则应在嵌入式软件中或多或少禁止使用malloc(在C ++中为“ new”关键字)。
糟糕,在嵌入式编程中,有时(经常)C不够底层,您需要执行一些操作,例如将变量分配给寄存器,并编写内联汇编以加强中断服务例程(ISR)。诸如“ volatile”之类的关键字变得非常重要,难以理解。您花费大量时间在位级别而不是对象级别上操作内存。
您为什么要自欺欺人地认为事情比实际上简单?
</ rant>