有什么理由使用 C 而不是 C++ 用于嵌入式开发?

发布于 2024-07-18 04:57:47 字数 1704 浏览 10 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(29

沧笙踏歌 2024-07-25 04:57:47

对于非常资源受限的目标(例如 4KB RAM),我会在投入大量无法轻松移植回纯 ANSI C 实现的工作之前使用一些示例进行测试。

嵌入式 C++ 工作组确实提出了该语言的标准子集以及与其配套的标准库的标准子集。 不幸的是,当 C User's Journal 消失后,我就失去了对这一努力的追踪。 看起来 Wikipedia 上有一篇文章,并且 委员会仍然存在。

在嵌入式环境中,您确实必须小心内存分配。 为了加强这种关注,您可能需要将全局operator new()及其友元定义为甚至无法链接的东西,以便您知道它没有被使用。 另一方面,如果明智地与稳定、线程安全和延迟保证的分配方案一起使用,则放置 new 可能会成为您的朋友。

内联函数不会造成太大问题,除非它们足够大,以至于它们一开始就应该是真正的函数。 当然,他们替换的宏也有同样的问题。

模板也可能不会引起问题,除非它们的实例化失控。 对于您使用的任何模板,请审核生成的代码(链接映射可能有足够的线索)以确保仅发生您打算使用的实例化。

可能出现的另一问题是与调试器的兼容性。 对于其他可用的硬件调试器来说,对与原始源代码的交互的支持非常有限,这并不罕见。 如果您实际上必须在汇编中进行调试,那么 C++ 中有趣的名称修改会给任务带来额外的混乱。

RTTI、动态转换、多重继承、重度多态性和异常在使用时都会产生一定的运行时成本。 其中一些功能级别如果使用的话会花费整个程序的成本,其他功能只会增加需要它们的类的权重。 了解差异,并在充分了解至少粗略的成本/效益分析的情况下明智地选择高级功能。

在小型嵌入式环境中,您将直接链接到实时内核或直接在硬件上运行。 无论哪种方式,您都需要确保运行时启动代码正确处理 C++ 特定的启动杂务。 这可能就像确保使用正确的链接器选项一样简单,但由于直接控制上电复位入口点的源很常见,因此您可能需要对其进行审核以确保它执行所有操作。 例如,在我工作的 ColdFire 平台上,开发工具附带了一个 CRT0.S 模块,该模块包含 C++ 初始化程序,但已注释掉。 如果我直接从盒子里使用它,我会对那些构造函数从未运行过的全局对象感到困惑。

此外,在嵌入式环境中,通常需要在使用硬件设备之前对其进行初始化,如果没有操作系统和引导加载程序,那么就需要您的代码来完成这些工作。 您需要记住,全局对象的构造函数是在调用 main() 之前运行的,因此您需要修改本地 CRT0.S(或其等效项)以获得硬件初始化在调用全局构造函数之前完成。 显然,main() 的顶部已经太晚了。

For a very resource constrained target such as 4KB of RAM, I'd test the waters with some samples before committing a lot of effort that can't be easily ported back into a pure ANSI C implementation.

The Embedded C++ working group did propose a standard subset of the language and a standard subset of the standard library to go with it. I lost track of that effort when the C User's Journal died, unfortunately. It looks like there is an article at Wikipedia, and that the committee still exists.

In an embedded environment, you really have to be careful about memory allocation. To enforce that care, you may need to define the global operator new() and its friends to something that can't be even linked so that you know it isn't used. Placement new on the other hand is likely to be your friend, when used judiciously along with a stable, thread-safe, and latency guaranteed allocation scheme.

Inlined functions won't cause much problem, unless they are big enough that they should have been true functions in the first place. Of course the macros their replacing had that same issue.

Templates, too, may not cause a problem unless their instantiation runs amok. For any template you do use, audit your generated code (the link map may have sufficient clues) to make certain that only the instantiations you intended to use happened.

One other issue that may arise is compatibility with your debugger. It isn't unusual for an otherwise usable hardware debugger to have very limited support for interaction with the original source code. If you effectively must debug in assembly, then the interesting name mangling of C++ can add extra confusion to the task.

RTTI, dynamic casts, multiple inheritance, heavy polymorphism, and exceptions all come with some amount of runtime cost for their use. A few of those features level that cost over the whole program if they are used, others just increase the weight of classes that need them. Know the difference, and choose advanced features wisely with full knowledge of at least a cursory cost/benefit analysis.

In an small embedded environment you will either be linking directly to a real time kernel or running directly on the hardware. Either way, you will need to make certain that your runtime startup code handles C++ specific startup chores correctly. This might be as simple as making sure to use the right linker options, but since it is common to have direct control over the source to the power on reset entry point, you might need to audit that to make certain that it does everything. For example, on a ColdFire platform I worked on, the dev tools shipped with a CRT0.S module that had the C++ initializers present but comment out. If I had used it straight from the box, I would have been mystified by global objects whose constructors had never run at all.

Also, in an embedded environment, it is often necessary to initialize hardware devices before they can be used, and if there is no OS and no boot loader, then it is your code that does that. You will need to remember that constructors for global objects are run before main() is called so you will need to modify your local CRT0.S (or its equivalent) to get that hardware initialization done before the global constructors themselves are called. Obviously, the top of main() is way too late.

z祗昰~ 2024-07-25 04:57:47

使用 C 而不是 C++ 的两个原因:

  1. 对于很多嵌入式处理器,要么没有 C++ 编译器,要么必须为此支付额外费用。
  2. 我的经验是,很大一部分嵌入式软件工程师很少或根本没有 C++ 经验——要么是因为 (1),要么是因为它往往不会在电子工程学位上教授——所以最好坚持使用他们知道什么。

另外,最初的问题和一些评论提到了 4 Kb RAM。 对于典型的嵌入式处理器,RAM 的数量(大部分)与代码大小无关,因为代码是在闪存中存储和运行的。

当然,代码存储空间的大小是需要记住的事情,但随着市场上出现新的、容量更大的处理器,除了对成本最敏感的项目之外,对于所有项目来说,这都不再是一个问题了。

关于使用 C++ 子集用于嵌入式系统:现在有一个 MISRA C++ 标准,这可能值得一看。

编辑:另请参阅此问题,它引发了关于嵌入式系统的 C 与 C++ 的争论。

Two reasons for using C over C++:

  1. For a lot of embedded processors, either there is no C++ compiler, or you have to pay extra for it.
  2. My experience is that a signficant proportion of embedded software engineers have little or no experience of C++ -- either because of (1), or because it tends not to be taught on electronic engineeering degrees -- and so it would be better to stick with what they know.

Also, the original question, and a number of comments, mention the 4 Kb of RAM. For a typical embedded processor, the amount of RAM is (mostly) unrelated to the code size, as the code is stored, and run from, flash.

Certainly, the amount of code storage space is something to bear in mind, but as new, more capacious, processors appear on the market, it's less of an issue than it used to be for all but the most cost-sensitive projects.

On the use of a subset of C++ for use with embedded systems: there is now a MISRA C++ standard, which may be worth a look.

EDIT: See also this question, which led to a debate about C vs C++ for embedded systems.

ぽ尐不点ル 2024-07-25 04:57:47

不会。在进行嵌入式开发时,可以避免任何可能导致问题的 C++ 语言功能(运行时多态性、RTTI 等)。 有一个嵌入式 C++ 开发人员社区(我记得在旧的 C/C++ 用户杂志中读过使用 C++ 的嵌入式开发人员的专栏),我无法想象如果选择那么糟糕,他们会大声疾呼。

No. Any of the C++ language features that could cause problems (runtime polymorphism, RTTI, etc.) can be avoided while doing embedded development. There is a community of embedded C++ developers (I remember reading columns by embedded developers using C++ in the old C/C++ Users' Journal), and I can't imagine they'd be very vocal if the choice was that bad.

梦中楼上月下 2024-07-25 04:57:47

C++ 性能技术报告 是一个很好的指南这种事。 请注意,它有一个关于嵌入式编程问题的部分!

另外,++ 在答案中提到了嵌入式 C++。 该标准并不 100% 符合我的口味,但在决定您可能放弃 C++ 的哪些部分时,它是一个很好的参考。

在为小型平台编程时,我们禁用异常和 RTTI,避免虚拟继承,并密切关注我们现有的虚拟函数的数量。

不过,你的朋友是链接器映射:经常检查它,你会很快发现代码源和静态内存膨胀。

之后,标准动态内存使用注意事项适用:在像您提到的那样受限制的环境中,您可能根本不希望使用动态分配。 有时,您可以使用内存池进行小型动态分配,或者使用“基于帧”的分配,即预先分配一个块,然后将整个块丢弃。

The Technical Report on C++ Performance is a great guide for this sort of thing. Note that it has a section on embedded programming concerns!

Also, ++ on the mention of Embedded C++ in the answers. The standard is not 100% to my tastes, but it is a good bit of reference when deciding what parts of C++ you might drop.

While programming for small platforms, we disable exceptions and RTTI, avoided virtual inheritance, and paid close attention to the number of virtual functions we have lying around.

Your friend is the linker map, though: check it frequently, and you'll spot sources of code and static memory bloat quickly.

After that, the standard dynamic memory usage considerations apply: in an environment as restricted as the one you mention, you may want to not use dynamic allocations at all. Sometimes you can get away with memory pools for small dynamic allocs, or "frame-based" allocation where you preallocate a block and throw out the whole thing later.

灵芸 2024-07-25 04:57:47

我建议使用 C++ 编译器,但限制您对 C++ 特定功能的使用。 您可以像 C++ 中的 C 一样进行编程(执行 C++ 时包含 C 运行时,但在大多数嵌入式应用程序中您无论如何都不使用标准库)。

您可以继续使用 C++ 类等,只需

  • 限制您对虚拟函数的使用(如您所说)
  • 限制您对模板的使用
  • 对于嵌入式平台,您需要重写运算符 new 和/或使用放置 new用于内存分配。

I recommend using the C++ compiler, but limiting your use of C++ specific features. You can program like C in C++ (the C runtime is included when doing C++, though in most embedded applications you don't make use of the standard library anyway).

You can go ahead and use C++ classes etc., just

  • Limit your use of virtual functions (as you've said)
  • Limit your use of templates
  • For an embedded platform, you'll want to override the operator new and/or use placement new for memory allocation.
月竹挽风 2024-07-25 04:57:47

作为一名固件/嵌入式系统工程师,我可以告诉大家为什么 C 仍然是 C++ 的第一选择的一些原因,是的,我对这两种语言都很熟悉。

1) 我们开发的一些目标有 64kB RAM 用于代码和数据,所以你必须确保每个字节计数,是的,我已经处理了代码优化以节省 4 个字节,这花了我 2 个小时,这在2008.

2)每个C库函数在我们放入最终代码之前都会经过审查,因为大小限制,所以我们希望人们不要使用divide(没有硬件除法器,所以需要一个大的库),malloc(因为我们有没有堆,所有内存都是从 512 字节块的数据缓冲区中分配的,并且必须进行代码审查),或其他带来巨大损失的面向对象实践。 请记住,您使用的每个库函数都很重要。

3)听说过“覆盖”这个词吗? 您的代码空间太小,有时您必须用另一组代码交换内容。 如果调用库函数,则该库函数必须是常驻的。 如果您仅在覆盖函数中使用它,那么您会依赖太多面向对象的方法而浪费大量空间。 因此,不要假设任何 C 库函数,更不用说 C++ 被接受。

4) 由于有限的硬件设计(即以某种方式连接的 ECC 引擎)或为了应对硬件错误,需要进行转换甚至打包(其中未对齐的数据结构跨越字边界)。 你不能隐式地假设太多,那么为什么要过度面向对象呢?

5) 最坏的情况:消除一些面向对象的方法将迫使开发人员在使用可能爆炸的资源之前进行思考(即在堆栈上分配 512 字节而不是从数据缓冲区中分配),并防止出现一些潜在的最坏情况没有测试或消除整个代码路径。

6)我们确实使用了大量的抽象来使硬件远离软件,并使代码尽可能可移植且易于模拟。 硬件访问必须封装在宏或内联函数中,这些函数在不同平台之间有条件地编译,数据类型必须转换为字节大小而不是特定于目标的,不允许直接使用指针(因为某些平台假设内存映射 I/O 是与数据存储器相同)等。

我可以想到更多,但你明白了。 我们的固件人员确实接受过面向对象的培训,但是嵌入式系统的任务可能是面向硬件的和低级别的,以至于它本质上不是高级的或可抽象的。

顺便说一句,我从事的每个固件工作都使用源代码控制,我不知道你从哪里得到这个想法。

-SanDisk 的一些固件专家。

As a firmware/embedded system engineer, I can tell you guys some of the reason why C is still the #1 choice over C++ and yes, I'm fluent in both of them.

1) Some targets we develop on has 64kB of RAM for both code and data, so you have to make sure every byte count, and yes, I've dealt with code optimization to save 4 bytes that cost me 2 hours, and that's in 2008.

2) Every C library function is reviewed before we let them in the final code, because of size limitation, so we prefer people not to use divide (no hardware divider, so a big library is needed), malloc (because we have no heap, all memory is allocated from data buffer in 512 byte chunk and must be code reviewed), or other object oriented practice that carry large penalty. Remember, every library function that you use count.

3) Ever heard of the term overlay? you have so little code space that sometimes you have to swap things out with another set of code. If you call a library function then the library function must be resident. If you only use it in an overlay function, you are wasting a lot of space relying on too many object oriented methods. So, don't assume any C library function, let alone C++ to be accepted.

4) Casting and even packing (where unaligned data structure crosses word boundary) are needed due to limited hardware design (i.e. an ECC engine that is wired a certain way) or to cope with a hardware bug. You cannot assume too much inplicitly, so why object orient it too much?

5) Worst case scenario: eliminating some of the object oriented methods will force develop to think before they use resources that can explode (i.e. allocating 512bytes on a stack rather than from a data buffer), and prevent some of the potential worst case scenario that are not tested for or eliminate the whole code path all together.

6) We do use a lot of abstraction to keep hardware from software and make code as portable as possible, and simulation friendly. Hardware access must be wrapped in a macro or inline function that are conditionally compiled between different platform, data type must be casted as byte size rather than target specific, direct pointer usage is not allowed (because some platform assume memory mapped I/O is the same as data memory), etc.

I can think of more, but you get the idea. Us firmware guys do have object oriented training, but the task of embedded system can be so hardware oriented and low level, that it is not high level or abstractable by nature.

BTW, every firmware job I've been at uses source control, I don't know where you get that idea from.

-some firmware guy from SanDisk.

痴情 2024-07-25 04:57:47

我听说有些人更喜欢用 C 语言进行嵌入式工作,因为它更简单,因此更容易预测将生成的实际代码。

我个人认为编写 C 风格的 C++(使用类型安全模板)会给你带来很多优势,而且我看不出有什么真正的理由不这样做。

I have heard that some people prefer C for embedded work due to the fact that is simpler and therefore easier to predict the actual code that will be generated.

I personally would think writing C-style C++ (using templates for type-safety) would give you a lot of advantages though and I can't see any real reason not to.

说谎友 2024-07-25 04:57:47

我个人偏好是 C,因为:

  • 我知道每行代码在做什么(以及成本)
  • 我不太了解 C++,无法了解每行代码的作用(以及成本)

为什么人们这么说? 除非检查 asm 输出,否则您知道 C 的每一行在做什么。 C++ 也是如此。

例如,这个无辜的语句会生成什么 asm:

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

它看起来相当无辜,但是基于 gcc 的编译器为 8 位微生成此 asm

CLRF 0x1f, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1f, F, ACCESS
MOVWF 0x1e, ACCESS
MOVLW 0xf9
MOVF 0xfdb, W, ACCESS
ADDWF 0x1e, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfa
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1f, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x1c
NOP
MOVFF 0xfef, 0x1d
NOP
MOVLW 0x1
CLRF 0x1b, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1b, F, ACCESS
MOVWF 0x1a, ACCESS
MOVLW 0xfb
MOVF 0xfdb, W, ACCESS
ADDWF 0x1a, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfc
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1b, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x18
NOP
MOVFF 0xfef, 0x19
NOP
MOVFF 0x18, 0x8
NOP
MOVFF 0x19, 0x9
NOP
MOVFF 0x1c, 0xd
NOP
MOVFF 0x1d, 0xe
NOP
CALL 0x2142, 0
NOP
MOVFF 0x6, 0x16
NOP
MOVFF 0x7, 0x17
NOP
CLRF 0x15, ACCESS
RLCF 0xfdf, W, ACCESS
ANDLW 0xfe
RLCF 0x15, F, ACCESS
MOVWF 0x14, ACCESS
MOVLW 0xfd
MOVF 0xfdb, W, ACCESS
ADDWF 0x14, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfe
MOVF 0xfdb, W, ACCESS
ADDWFC 0x15, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0x16, 0xfee
NOP
MOVFF 0x17, 0xfed
NOP

生成的指令数量很大程度上取决于:

  • a、b 和 c 的大小。
  • 这些指针是否存储在堆栈上还是全局的
  • i、j 和 k 是否在堆栈上还是全局的

这在微小的嵌入式世界中尤其如此,其中处理器未设置为处理 C。所以我的答案是C 和 C++ 彼此一样糟糕,除非您总是检查 asm 输出,在这种情况下它们彼此一样好。

雨果

My personal preference is C because :

  • I know what every line of code is doing (and costs)
  • I don't know C++ well enough to know what every line of code is doing (and costs)

Why do people say this? You don't know what every line of C is doing unless you check the asm output. Same goes for C++.

For example, what asm does this innocent statement produce:

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

It looks fairly innocent, but a gcc based compiler produces this asm for an 8-bit micro

CLRF 0x1f, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1f, F, ACCESS
MOVWF 0x1e, ACCESS
MOVLW 0xf9
MOVF 0xfdb, W, ACCESS
ADDWF 0x1e, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfa
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1f, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x1c
NOP
MOVFF 0xfef, 0x1d
NOP
MOVLW 0x1
CLRF 0x1b, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1b, F, ACCESS
MOVWF 0x1a, ACCESS
MOVLW 0xfb
MOVF 0xfdb, W, ACCESS
ADDWF 0x1a, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfc
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1b, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x18
NOP
MOVFF 0xfef, 0x19
NOP
MOVFF 0x18, 0x8
NOP
MOVFF 0x19, 0x9
NOP
MOVFF 0x1c, 0xd
NOP
MOVFF 0x1d, 0xe
NOP
CALL 0x2142, 0
NOP
MOVFF 0x6, 0x16
NOP
MOVFF 0x7, 0x17
NOP
CLRF 0x15, ACCESS
RLCF 0xfdf, W, ACCESS
ANDLW 0xfe
RLCF 0x15, F, ACCESS
MOVWF 0x14, ACCESS
MOVLW 0xfd
MOVF 0xfdb, W, ACCESS
ADDWF 0x14, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfe
MOVF 0xfdb, W, ACCESS
ADDWFC 0x15, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0x16, 0xfee
NOP
MOVFF 0x17, 0xfed
NOP

The number of instructions produced depends massively on:

  • The sizes of a, b, and c.
  • whether those pointers are stored on the stack or are global
  • whether i, j and k are on the stack or are global

This is especially true in the tiny embedded world, where processors are just not set up to handle C. So my answer would be that C and C++ are just as bad as each other, unless you always examine the asm output, in which case they are just as good as each other.

Hugo

他夏了夏天 2024-07-25 04:57:47

我认为没有理由使用 C 而不是 C++。 无论你能用 C 做什么,你也可以用 C++ 做。 如果您想避免 VMT 的开销,请不要使用虚拟方法和多态性。

然而,C++ 可以提​​供一些非常有用的习惯用法,而无需任何开销。 我最喜欢的之一是 RAII。 类在内存或性能方面不一定昂贵......

I see no reason to use C instead of C++. Whatever you can do in C, you can do it also in C++. If you want to avoid overheads of VMT, don't use virtual methods and polymorphism.

However, C++ can provide some very useful idioms with no overhead. One of my favourites is RAII. Classes are not necessary expensive in terms of memory or performance...

兰花执着 2024-07-25 04:57:47

人类大脑通过尽可能多地评估来处理复杂性,然后决定重点关注什么,并丢弃或贬低其余的。 这是营销中品牌(主要是图标)背后的全部基础。

为了对抗这种趋势,我更喜欢 C 而不是 C++,因为它迫使你思考你的代码,以及它如何与硬件更紧密地交互——无情地紧密。

根据长期的经验,我相信 C 迫使你想出更好的问题解决方案,部分原因是让你摆脱困境,而不是强迫你浪费大量时间来满足某些编译器作者认为是个好主意的约束,或者弄清楚“幕后”发生了什么。

在这种情况下,像 C 这样的低级语言会让您花费大量时间专注于硬件并构建良好的数据结构/算法包,而高级语言则让您花费大量时间挠头想知道里面发生了什么,以及为什么你不能在你的特定背景和环境中做一些完全合理的事情。 让编译器屈服(强类型是最严重的罪犯)并不是对时间的有效利用。

我可能很适合程序员的模式——我喜欢控制。 在我看来,这并不是程序员的性格缺陷。 控制是我们获得报酬所做的事情。 更具体地说,是完美的控制。 C 比 C++ 给你更多的控制权。

The human mind deals with complexity by evaluating as much as possible, and then deciding what's important to focus on, and discarding or depreciating the rest. This is the entire underpinning behind branding in Marketing, and largely, icons.

To combat this tendency I prefer C to C++, because it forces you to think about your code, and how it's interacting with the hardware more closely - relentlessly close.

From long experience it is my belief that C forces you to come up with better solutions to problems, in part, by getting out of your way and not forcing you to waste lots of time satisfying a constraint some compiler-writer thought was a good idea, or figuring out what's going on "under the covers".

In that vein, low level languages like C have you spending a lot of time focused on the hardware and building good data-structure/algorithm bundles, while high level languages have you spending a lot of time scratching your head wondering what's going on in there, and why you can't do something perfectly reasonable in your specific context and environment. Beating your compiler into submission (strong typing is the worst offender) is NOT a productive use of time.

I probably fit the programmer mold well - I like control. In my view, that's not a personality flaw for a programmer. Control is what we get paid to do. More specifically, FLAWLESSLY control. C gives you much more control than C++.

贪恋 2024-07-25 04:57:47

我在 IAR Workbench 上为 ARM7 嵌入式平台编写了一些代码。 我强烈建议依靠模板来进行编译时优化和路径预测。 避免像瘟疫一样进行动态转换。 按照 Andrei Alexandrescu 的书 现代 C++ 设计

我知道,这可能很难学习,但我也确信您的产品将从这种方法中受益。

I've written some code for ARM7 embedded paltform on IAR Workbench. I highly recommend relying on templates to do compile-time optimization and path prediction. Avoid dynamic casting like plague. Use traits/policies to your advantage, as prescribed in Andrei Alexandrescu's book, Modern C++ design.

I know, it can be hard to learn, but I am also sure that your product will benefit from this approach.

九命猫 2024-07-25 04:57:47

对于限制为 4K 内存的系统,我会使用 C,而不是 C++,这样您就可以确保看到正在发生的一切。 C++ 的问题在于,使用比看起来代码多得多的资源(CPU 和内存)非常容易。 (哦,我将创建另一个 BlerfObject 来执行此操作...哎呀!内存不足!)

您可以用 C++ 执行此操作,如前所述(没有 RTTI,没有 vtables 等),但是您将花费确保您使用 C++ 的时间不会像在 C 中执行等效操作一样多。

For a system constrained to 4K of ram, I would use C, not C++, just so that you can be sure to see everything that's going on. The thing with C++, is that it's very easy to use far more resources (both CPU and memory) than it looks like glancing at the code. (Oh, I'll just create another BlerfObject to do that...whoops! out of memory!)

You can do it in C++, as already mentioned (no RTTI, no vtables, etc, etc), but you'll spend as much time making sure your C++ usage doesn't get away from you as you would doing the equivalent in C.

雄赳赳气昂昂 2024-07-25 04:57:47

一个很好的原因,有时也是唯一的原因是,仍然没有针对特定嵌入式系统的 C++ 编译器。 Microchip PIC 微控制器就是这种情况。 它们非常容易编写,并且有一个免费的 C 编译器(实际上是 C 的一个轻微变体),但目前还没有 C++ 编译器。

A good reason and sometimes the only reason is that there is still no C++ compiler for the specific embedded system. This is the case for example for Microchip PIC micro-controllers. They are very easy to write for and they have a free C compiler (actually, a slight variant of C) but there is no C++ compiler in sight.

南风几经秋 2024-07-25 04:57:47

就我个人而言,对于 4kb 内存,我认为您不会从 C++ 中获得更多收益,因此只需选择一个似乎最适合该工作的编译器/运行时组合,因为语言可能并不那么重要。

请注意,无论如何,这也不仅仅与语言有关,因为图书馆也很重要。 通常,C 库的最小大小会稍小一些,但我可以想象,针对嵌入式开发的 C++ 库会被缩减,因此请务必进行测试。

Personally with 4kb of memory I'd say you are not getting that much more mileage out of C++, so just pick the one that seems the best compiler/runtime combination for the job, since language is probably not going to matter much.

Note that it is also not all about language anyway, since also the library matters. Often C libs have a slightly smaller minimum size, but I could imagine that a C++ lib targeted at embedded development is cut down, so be sure to test.

黯然#的苍凉 2024-07-25 04:57:47

C 在可移植性上获胜——因为它在语言规范上不那么模糊; 因此,在不同的编译器等之间提供更好的可移植性和灵活性(更少的麻烦)。

如果您不打算利用 C++ 功能来满足需求,那么就选择 C。

C wins on portability - because it is less ambiguous in language spec; therefore offering much better portability and flexibility across different compilers etc (less headaches).

If you aren't going to leverage C++ features to meet a need then go with C.

小…楫夜泊 2024-07-25 04:57:47

当开发内容非常有限时,您认为有什么理由坚持使用 C89
硬件(4kb RAM)?

就我个人而言,当谈到嵌入式应用程序时(当我说嵌入式时,我并不是指winCE、iPhone等当今臃肿的嵌入式设备)。 我的意思是资源有限的设备。
我更喜欢 C,尽管我也经常使用 C++。

例如,您正在谈论的设备有 4kb RAM,只是因为这个原因我不会考虑C++。 当然,您也许可以使用 C++ 设计一些小东西,并像其他帖子所建议的那样限制在应用程序中使用它,但 C++“可能”最终会在幕后使您的应用程序变得复杂/膨胀。

你要静态链接吗? 您可能想比较使用 C++ 和 C 的静态虚拟应用程序。 这可能会导致您考虑使用 C。 另一方面,如果您能够在内存需求范围内构建 C++ 应用程序,那就去做吧。

恕我直言,
一般来说,在嵌入式应用程序中,我喜欢了解正在发生的一切。 谁在使用内存/系统资源、使用量以及原因? 他们什么时候释放他们?

当开发具有 X 数量资源、CPU、内存等的目标时。我尝试保持使用这些资源的较低水平,因为你永远不知道未来会出现什么需求,因此需要向项目添加更多代码“应该”是一个简单的小应用程序,但最终变得更大。

Do you see any reason to stick with C89 when developing for very limited
hardware (4kb of RAM)?

Personally, when it comes to embedded applications (When I say embedded, I don't mean winCE, iPhone, etc.. bloated embedded devices today). I mean resource limited devices.
I prefer C, though I have worked with C++ quite a bit as well.

For example, the device you're talking about has 4kb of RAM, well just for that reason I wouldn't consider C++. Sure, you may be able to design something small using C++ and limit your usage of it in your application like other posts have suggested but C++ "could" potentially end up complicating/bloating your application under the covers.

Are you going to link statically? You may want to compare static a dummy application using c++ vs c. That may lead you to consider C instead. On the other hand if you are able to build a C++ application within your memory requirements, go for it.

IMHO,
In general, in embedded applications I like to know everything that is going on. Who's using memory/system resources, how much and why? When do they free them up?

When developing for a target with X amount of resources, cpu, memory, etc.. I try to stay on the lower side of using those resources because you never know what future requirements will come along thus having you add more code to the project that was "supposed" to be a simple small application but ends up becoming a lot bigger.

原谅过去的我 2024-07-25 04:57:47

我的选择通常是由我们决定使用的C库决定的,这是根据设备需要做什么来选择的。 所以,9/10 次..最终会变成 uclibc 或 newlib 和 C。我们使用的内核对此也有很大的影响,或者如果我们正在编写自己的内核。

这也是一种共同点的选择。 大多数优秀的 C 程序员在使用 C++ 时都没有问题(尽管许多人在使用它的整个过程中都在抱怨)。但我还没有发现相反的情况是正确的(根据我的经验)。

在我们正在进行的一个项目(涉及底层内核)中,大多数事情都是用 C 完成的,但是一个小型网络堆栈是用 C++ 实现的,因为使用 C++ 实现网络更容易且问题更少。

最终结果是,该设备要么可以工作并通过验收测试,要么不能。 如果您可以使用 z 语言在 xx 堆栈和 yy 堆约束中实现 foo,那就去做吧,使用任何能让您提高工作效率的东西。

我个人偏好 C,因为:

  • 我知道每一行代码在做什么(和成本)
  • 我不太了解 C++,无法知道每一行代码在做什么(和成本)

是的,我对 C++ 很满意,但是我对它的了解不如我对标准 C 的了解。

现在,如果你能说相反的话,那么,使用你所知道的:)如果它有效,通过测试等..有什么问题?

My choice is usually determined by the C library we decide to use, which is selected based on what the device needs to do. So, 9/10 times .. it ends up being uclibc or newlib and C. The kernel we use is a big influence on this too, or if we're writing our own kernel.

Its also a choice of common ground. Most good C programmers have no problem using C++ (even though many complain the entire time that they use it) .. but I have not found the reverse to be true (in my experience).

On a project we're working on (that involves a ground up kernel), most things are done in C, however a small network stack was implemented in C++, because it was just easier and less problematic to implement networking using C++.

The end result is, the device will either work and pass acceptance tests or it won't. If you can implement foo in xx stack and yy heap constraints using language z, go for it, use whatever makes you more productive.

My personal preference is C because :

  • I know what every line of code is doing (and costs)
  • I don't know C++ well enough to know what every line of code is doing (and costs)

Yes, I am comfortable with C++, but I don't know it as well as I do standard C.

Now if you can say the reverse of that, well, use what you know :) If it works, passes tests, etc .. what's the problem?

高速公鹿 2024-07-25 04:57:47

你有多少 ROM/FLASH?

4kB 的 RAM 仍然意味着有数百 KB 的闪存来存储实际代码和静态数据。 这种大小的 RAM 往往只适用于变量,如果您小心使用这些变量,您可以将相当大的程序(就代码行而言)放入内存中。

然而,由于对象的运行时构造规则,C++ 往往会使将代码和数据放入 FLASH 中变得更加困难。 在 C 语言中,常量结构可以轻松放入闪存并作为硬件常量对象进行访问。 在C++中,常量对象需要编译器在编译时评估构造函数,我认为这仍然超出了C++编译器的能力范围(理论上,你可以做到,但实际上很难做到) 。

因此,在“小 RAM”、“大闪存”类型的环境中,我随时都会选择 C。 请注意,C99 是一个不错的中间选择,它具有适用于非基于类的代码的大部分良好的 C++ 功能。

How much ROM/FLASH do you have?

4kB of RAM can still mean there are hundreds of kilobytes of FLASH to store the actual code and static data. RAM on this size tends to be meant just for variables, and if you are careful with those you can fit quite a large program in terms of code lines into memory.

However, C++ tends to make putting code and data in FLASH more difficult, due to the run-time construction rules for objects. In C, a constant struct can easily be put into FLASH memory and accessed as a hardware-constant object. In C++, a constant object would require the compiler to evaluate the constructor at compile-time, which I think is still beyond what a C++ compiler can do (theoretically, you could do it, but it is very very hard to do in practice).

So in a "small RAM", "large FLASH" kind of environment I would go with C any day. Note that a good intermediate choice i C99 which has most of the nice C++ features for non-class-based-code.

烈酒灼喉 2024-07-25 04:57:47

只是想说,不存在拥有“无限”资源的系统。 这个世界上的一切都是有限的,每个应用程序都应该考虑资源使用,无论是 ASM、C、JAVA 还是 JavaScript。 “只是为了确定”而分配几 Mb 的虚拟设备使得 iPhone 7、Pixel 和其他设备变得极其笨重。 无论您拥有 4kb 还是 40 GB。

但从另一个角度来看,反对资源浪费是需要时间来节省这些资源的。 如果额外花费 1 周的时间用 C 编写一个简单的东西来节省一些时间和一些字节,而不是使用已经实现、测试和分发的 C++。 何必呢? 就像买一个 USB 集线器一样。 是的,你可以自己做,但是会更好吗? 更可靠? 如果你算一下时间的话会更便宜吗?

只是一个侧面的想法 - 即使你的插座的电源也不是无限的。 尝试研究它的来源,你会发现它主要来自燃烧的东西。 能量和物质的定律仍然有效:物质或能量不会出现或消失,而是会发生变化。

Just want to say that there is no system with "UNLIMITED" resources. Everything in this world is limited and EVERY application should consider resource usage no matter whether its ASM, C, JAVA or JavaScript. The dummies that allocate a few Mbs "just to be sure" makes iPhone 7, Pixel and other devices extremely luggy. No matter whether you have 4kb or 40 Gb.

But from another side to oppose resource wasting - is a time that takes to save those resources. If it takes 1 week extra to write a simple thing in C to save a few ticks and a few bytes instead of using C++ already implemented, tested and distributed. Why bother? Its like buying a usb hub. yes you can make it yourself but is it going to be better? more reliable? cheaper if you count your time?

Just a side thought - even power from your outlet is not unlimited. Try to research where its coming from and you will see mostly its from burning something. The law of energy and material is still valid: no material or energy appears or disappears but rather transforms.

油饼 2024-07-25 04:57:47

一般来说没有。 C++ 是 C 的超集。对于新项目尤其如此。

您在避免使用 C++ 构造方面是正确的,因为 C++ 构造在 CPU 时间和内存占用方面可能会很昂贵。

请注意,像多态性这样的东西可能非常有价值——它们本质上是函数指针。 如果您发现需要它们,请明智地使用它们。

此外,良好的(精心设计的)异常处理可以使您的嵌入式应用程序比使用传统错误代码处理事务的应用程序更可靠。

In general no. C++ is a super set of C. This would be especially true for for new projects.

You are on the right track in avoiding C++ constructs that can be expensive in terms of cpu time and memory foot print.

Note that some things like polymorphism can be very valuable - the are essentially function pointers. If you find you need them, use them - wisely.

Also, good (well designed) exception handling can make your embedded app more reliable than an app that handles things with traditional error codes.

很糊涂小朋友 2024-07-25 04:57:47

对于内存分配问题,我建议使用 Quantum Platform 及其状态机方法,因为它会在初始化时分配您需要的所有内容。 它还有助于缓解争用问题。

该产品可在 C 和 C++ 上运行。

For memory allocation issue, I can recommend using Quantum Platform and its state machine approach, as it allocates everything you'd need at the initialization time. It also helps to alleviate contention problems.

This product runs on both C and C++.

我也只是我 2024-07-25 04:57:47

有人说 C 编译器可以生成更高效的代码,因为它们不必支持高级 C++ 功能,因此可以更积极地进行优化。

当然,在这种情况下,您可能想要测试两个特定的编译器。

Some say that C compilers can generate much more efficient code because they don't have to support the advanced C++ features and can therefore be more aggressive in their optimizations.

Of course, in this case you may want to put the two specific compilers to the test.

反目相谮 2024-07-25 04:57:47

恕我直言,选择 C ​​的唯一原因是您平台的 C++ 编译器状态不佳(有错误、优化不佳等)。

The only reason to prefer C IMHO would be if the C++ compiler for your platform is not in a good shape (buggy, poor optimization, etc).

夏天碎花小短裙 2024-07-25 04:57:47

你在 C99 中有内联。 也许你喜欢演员,但找到合适的演员可能会很麻烦。 如果不使用 C 的唯一原因是命名空间,那么我真的会坚持使用 C89。 这是因为您可能希望将其移植到稍微不同的嵌入式平台。 您稍后可以开始用 C++ 编写相同的代码。 但请注意以下内容,其中 C++ 不是 C 的超集。我知道您说过您有一个 C89 编译器,但无论如何都会将 C++ 与 C99 进行比较,因为例如第一项对于自 K&R 以来的任何 C 都是正确的。

'a'的大小> 1 在 C 中,而不是在 C++ 中。
在 C 中,有 VLA 可变长度数组。 示例:func(int i){int a[i]
在 C 中,您有 VAM 变量数组成员。 示例:struct{int b;int m[];}

You have inline in C99. Maybe you like ctors, but the business of getting dtors right can be messy. If the remaining only reason to not use C is namespaces, I would really stick to C89. This is because you might want to port it to a slightly different embedded platform. You may later start writing in C++ on that same code. But beware the following, where C++ is NOT a superset of C. I know you said you have a C89 compiler, but does this C++ comparison with C99 anyway, as the first item for example is true for any C since K&R.

sizeof 'a' > 1 in C, not in C++.
In C you have VLA variable length arrays. Example: func(int i){int a[i].
In C you have VAM variable array members. Example: struct{int b;int m[];}.

掩饰不了的爱 2024-07-25 04:57:47

这取决于编译器。

并非所有嵌入式编译器都实现了所有 C++,即使实现了,它们也可能无法很好地避免代码膨胀(这始终是模板的风险)。 用一些较小的程序对其进行测试,看看是否遇到任何问题。

但如果有一个好的编译器,就没有理由不使用 C++。

It depends on the compiler.

Not all embedded compilers implement all of C++, and even if they do, they might not be good at avoiding code bloat (which is always a risk with templates). Test it with a few smaller programs, see if you run into any problems.

But given a good compiler, no, there's no reason not to use C++.

风筝在阴天搁浅。 2024-07-25 04:57:47

我推荐带有限制和注释的 C++。

  1. 上市时间和可维护性。C++ 开发更容易、更快。 因此,如果您处于设计阶段,请选择一个足以使用 C++ 的控制器。 (请注意,一些大容量市场需要尽可能低的成本,而您无法做出这种选择。)

  2. 速度。C 可以比 C++ 更快,但请确保速度增益是不大。 所以你可以使用 C++。 开发您的算法,测试它们,并仅在需要时使它们更快(!)。 使用分析器,找出瓶颈并以extern "C"方式重写它们,以达到C速度。 (如果在 ASM 中实现该部分仍然很慢)

  3. 二进制大小。C++ 代码更大,但这里有一个 很好的答案,讲述了细节。 无论是使用 C 还是 C++ 编译器编译给定 C 代码,其编译后的二进制文件的大小都是相同的。 “可执行文件的大小与语言无关,而是与项目中包含的库相关。” 使用 C++,但避免使用高级功能,例如 streamsstringnewvirtual 函数等。由于大小限制(基于 这个答案)

I recommend C++ with limitations and notes.

  1. Time to market and maintainability. C++ development is easier and faster. So if you are in the designing phase, chose a controller great enough to use C++. (Note, that some high volume market requires as low cost as possible, where you cannot make this choice.)

  2. Speed. C can be faster than C++, but be sure this the speed gain is not big. So you can go with C++. Develop your algorithms, test them, and make them faster only if required(!). Use profilers, to point the bottlenecks and rewrite them in extern "C" way, to achieve C speed. (If it still slow implement that part in ASM)

  3. Binary size. The C++ codes are bigger, but here is a great answer that tells the details. The size of the compiled binary of a given C code will be the same whether it was compiled using the C or the C++ compiler. "The executable size is hardly related to the language, but to the libraries you include in your project." Go with C++ but avoid advanced functionalities, like streams, string, new, virtual functions, etc. Review all library function before letting them in the final code, because of size limitation (based on this answer)

随梦而飞# 2024-07-25 04:57:47

不同的答案针对问题的不同方面:

“malloc”

之前的一些回复对此进行了很多讨论。 你为什么认为这个电话存在? 对于真正的小型平台,malloc 往往不可用,或者绝对是可选的。 当您的系统底层有一个 RTOS 时,实现动态内存分配往往是有意义的——但在那之前,它纯粹是危险的。

没有它你也能走得很远。 想想所有旧的 FORTRAN 程序,它们甚至没有适当的局部变量堆栈......

Different answer post to a different aspect of the question:

"malloc"

Some previous replies talk quite a bit about this. Why do you even think that call exists? For a truly small platform, malloc tends to be unavailable, or definitely optional. Implementing dynamic memory allocation tends to be meaningful when you get to have an RTOS in the bottom of your system -- but until then, it is purely dangerous.

You can get very far without it. Just think about all the old FORTRAN programs which did not even have a proper stack for local variables...

攒眉千度 2024-07-25 04:57:47

全球有许多不同的控制器制造商,当您查看他们的设计和配置所需的指令集时,您可能会遇到很多麻烦。 汇编语言的主要缺点是依赖于机器/体系结构。 对于开发人员来说,牢记其中列出的所有指令以完成不同控制器的编码确实是一个巨大的要求。 这就是为什么 C 在嵌入式开发中变得更加流行,因为 C 的级别足够高,可以从依赖于硬件的细节中抽象出算法和数据结构,使源代码可以跨各种目标硬件、架构独立的语言移植,并且非常容易转换并维护代码。 但我们确实看到一些高级语言(面向对象),如 C、C++、Python、Java 等,已经足够发展,使它们受到嵌入式系统开发的关注。

There are a number of different controller manufacturers around the globe and when you take a look into their designs and the instruction sets that need to be used to configure you may end up in a lot of troubles. The main disadvantage of assembly language is that machine/architecture dependent. It’s really huge ask for a developer to by heart all the instructions set out there to accomplish coding for different controllers. That is why C became more popular in embedded development because C is high-level enough to abstract the algorithms and data structures from hardware-dependent details, making the source code portable across a wide variety of target hardware, architecture independent language and very easy to convert and maintain the code. But we do see some high-level languages (object-oriented) like C, C++, Python, Java etc. are evolving enough to make them under the radar of embedded system development.

倦话 2024-07-25 04:57:47

在这样一个有限的系统上。 只需选择汇编器即可。 让您完全控制各个方面,并且不产生任何开销。

可能也会快很多,因为很多嵌入式编译器都不是最好的优化器(特别是如果将它与最先进的编译器(例如我们用于桌面的编译器(英特尔、Visual Studio 等)进行比较))

“是的,是的.. .但是c是可重复使用的并且......”。 在这样一个有限的系统上,您很可能不会在不同的系统上重复使用大部分代码。 在同一系统上,汇编程序同样可以重复使用。

On such a limited system. Just go for Assembler. Gives you total control over every aspect, and gives no overhead.

Probably a lot faster too since a lot of embedded compilers are not the best optimizers (especially if one compares it to state of the art compilers like the ones we have for the desktop (intel, visual studio, etc))

"yeah yeah...but c is re-usable and...". On such a limited system, chances are you won't re-use much of that code on a different system anyway. On the same system, assembler is just as re-usable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文