組み込み開発にC ++の代わりにCを使用する理由はありますか?


82

質問

ハードウェアC ++とC89に2つのコンパイラがあります

クラスでC ++を使用することを考えていますが、ポリモーフィズムはありません(vtableを回避するため)。C ++を使用したい主な理由は次のとおりです。

  • マクロ定義の代わりに「インライン」関数を使用することを好みます。
  • プレフィックスがコードを乱雑にするので、名前空間を使用したいと思います。
  • C ++は、主にテンプレートと冗長なキャストのために、少しタイプが安全だと思います。
  • 私はオーバーロードされた関数とコンストラクター(自動キャストに使用される)が本当に好きです。

非常に限られたハードウェア(4kbのRAM)向けに開発する場合、C89を使い続ける理由はありますか?

結論

あなたの答えをありがとう、彼らは本当に役に立ちました!

私は主題を熟考しました、そして私は主に以下のためにCに固執します:

  1. Cで実際のコードを予測する方が簡単です。これは、RAMが4kbしかない場合に非常に重要です。
  2. 私のチームは主にC開発者で構成されているため、高度なC ++機能はあまり使用されません。
  3. Cコンパイラ(C89)で関数をインライン化する方法を見つけました。

あなたがたくさんの良い答えを提供したので、1つの答えを受け入れるのは難しいです。残念ながら、ウィキを作成して受け入れることができないので、私が最も考えさせられた答えを1つ選びます。


11
1つ:あなたが書いている言語を常に完全に明確にしてください。「C / C ++」でプログラムを書こうとしないでください。Cで書くか、C ++で書くと、使用する言語機能と使用しない言語機能がわかります。
デビッドソーン


「組み込み開発」を定義する
Marco van de Voort 2010年

@DavidThornley、埋め込みケースに適しているかもしれませんが、Kamailioのような一般的な業界のオープンソースアプリをSTLで拡張しようとしているときに、CとC ++のコードがうまく混在していることに非常に嬉しく思います。STLとCコードのこの使用法を公式に奨励しています。これは、すばらしい機能と今後のメンテナンスの容易さを提供し、問題をほとんど発生させないためです(C ++に埋め込まれた構造体がないことは、C ++に対する恐ろしい犯罪であり、できるだけ早く修正する必要があります) )。
user2548100 2014年

ZeroMQの設計者および作成者が、CではなくC ++でコードベースを記述したことを後悔している理由について説明しているすばらしい記事です。私が期待したことではなく、このページの他の場所にない理由もあります。250bpm.com/blog:4
user2548100

回答:


48

C ++ではなくCを使用する2つの理由:

  1. 多くの組み込みプロセッサでは、C ++コンパイラがないか、追加料金を支払う必要があります。
  2. 私の経験では、組み込みソフトウェアエンジニアのかなりの割合がC ++の経験をほとんどまたはまったく持っていません-(1)のため、または電子工学の学位で教えられない傾向があるため-したがって、固執する方が良いでしょう彼らが知っていること。

また、元の質問といくつかのコメントには、4KbのRAMが記載されています。一般的な組み込みプロセッサの場合、コードはフラッシュから保存および実行されるため、RAMの量は(ほとんど)コードサイズとは無関係です。

確かに、コードストレージスペースの量は覚えておくべきことですが、新しい、より容量の大きいプロセッサが市場に登場するにつれて、最もコストに敏感なプロジェクトを除いて、以前よりも問題は少なくなります。

組み込みシステムで使用するためのC ++のサブセットの使用について:MISRA C ++標準があり、一見の価値があるかもしれません。

編集:この質問も参照してください。これは、組み込みシステムのCとC ++についての議論につながりました。


2
以下の私の長い返信を参照してください。C++は、定数データをFLASHに入れることを非常に困難にする傾向があります。
jakobengblom2 2009年

3
C ++の代わりにCを使用する潜在的に正当な理由は、Cの標準ABIです。完全を期すためだけに。
クリス・ルッツ

66

以下のために非常なRAMの4キロバイトなどのリソースに制約のターゲット、私は純粋なANSI Cの実装に簡単に移植バックすることはできません多くの労力をコミットする前に、いくつかのサンプルと水をテストしたいです。

Embedded C ++ワーキンググループは、言語の標準サブセットとそれに対応する標準ライブラリの標準サブセットを提案しました。残念ながら、C User's Journalが亡くなったとき、私はその努力を見失いました。ウィキペディアに記事があり、委員会はまだ存在しているようです。

組み込み環境では、メモリの割り当てに本当に注意する必要があります。そのケアを実施するには、グローバルoperator new()とそのフレンドを、リンクすらできないものに定義して、使用されていないことがわかるようにする必要がある場合があります。new一方、配置は、安定した、スレッドセーフで、遅延が保証された割り当てスキームとともに慎重に使用すると、友だちになる可能性があります。

インライン関数は、そもそも真の関数であるはずの大きさでない限り、それほど問題にはなりません。もちろん、それらを置き換えるマクロにも同じ問題がありました。

テンプレートも、インスタンス化がうまくいかない限り、問題を引き起こさない可能性があります。使用するテンプレートについては、生成されたコードを監査して(リンクマップに十分な手がかりがある場合があります)、使用する予定のインスタンス化のみが発生したことを確認します。

発生する可能性のあるもう1つの問題は、デバッガーとの互換性です。他の方法で使用できるハードウェアデバッガーが、元のソースコードとの対話のサポートが非常に限られていることは珍しいことではありません。アセンブリで効果的にデバッグする必要がある場合は、C ++の興味深い名前マングリングにより、タスクがさらに混乱する可能性があります。

RTTI、動的キャスト、多重継承、重いポリモーフィズム、および例外はすべて、それらを使用するためにある程度の実行時コストが伴います。これらの機能のいくつかは、使用された場合にプログラム全体でコストがかかるレベルですが、その他の機能は、それらを必要とするクラスの重みを増やすだけです。違いを理解し、少なくとも大まかな費用便益分析の完全な知識を備えた高度な機能を賢く選択してください。

小さな組み込み環境では、リアルタイムカーネルに直接リンクするか、ハードウェアで直接実行します。いずれにせよ、ランタイムスタートアップコードがC ++固有のスタートアップの雑用を正しく処理することを確認する必要があります。これは、適切なリンカーオプションを使用するのと同じくらい簡単かもしれませんが、ソースをパワーオンリセットエントリポイントに直接制御するのが一般的であるため、それを監査して、すべてが実行されることを確認する必要があります。たとえば、私が取り組んだColdFireプラットフォームでは、開発ツールにはC ++イニシャライザーが存在するがコメントアウトされたCRT0.Sモジュールが付属しています。箱から出してすぐに使用したとしたら、コンストラクターがまったく実行されたことがないグローバルオブジェクトに不思議に思っていたでしょう。

また、組み込み環境では、ハードウェアデバイスを使用する前に初期化する必要があることが多く、OSとブートローダーがない場合は、それを行うのはコードです。グローバルオブジェクトのコンストラクターは呼び出される前に 実行さmain()れるため、グローバルコンストラクター自体が呼び出される前にハードウェアの初期化が行われるようにローカルCRT0.S(または同等のもの)を変更する必要があることを覚えておく必要があります。明らかに、トップmain()は遅すぎます。


1
これは私がそれを与えることができるより多くの賛成票を必要とします!素晴らしい答え。
ハーパーシェルビー

+1、素晴らしい答え。しかし、本当に心配する必要があるテンプレートのインスタンス化は、(比較的まれな)再帰的な種類だけだと思います。「通常の」非再帰的な種類の場合、インスタンス化は、とにかく手動で入力したコードに相当します。
j_random_hacker 2009年

2
@j_random_hacker、本当。ただし、テンプレートの習慣により、使用時に適切な型強制が行われなかった可能性がある2番目(または3番目)のインスタンス化が表示されると、ときどき驚きが生じる可能性があります。気をつけるべきことです。
RBerteig 2009年

@RBerteig:良い点ですが、テンプレートでは型強制の可能性が少なくなります=>テンプレート以外のコードよりも明確なインスタンス化が生成される可能性があります。
j_random_hacker 2009年

26

いいえ。組み込み開発を行う際に、問題を引き起こす可能性のあるC ++言語機能(実行時ポリモーフィズム、RTTIなど)を回避できます。組み込みC ++開発者のコ​​ミュニティがあり(古いC / C ++ユーザージャーナルでC ++を使用して組み込み開発者によるコラムを読んだことを覚えています)、選択がそれほど悪かった場合、彼らが非常に声高になるとは想像できません。


20

C ++のパフォーマンス上の技術報告書は、この種のもののための素晴らしいガイドです。組み込みプログラミングの懸念に関するセクションがあることに注意してください!

また、回答でのEmbedded C ++の言及に関する++。この標準は私の好みに100%ではありませんが、C ++のどの部分を削除するかを決定する際の参考になります。

小さなプラットフォーム向けにプログラミングするときは、例外とRTTIを無効にし、仮想継承を回避し、存在する仮想関数の数に細心の注意を払いました。

ただし、あなたの友達はリンカーマップです。頻繁にチェックすると、コードのソースと静的メモリの肥大化をすばやく見つけることができます。

その後、標準の動的メモリ使用量に関する考慮事項が適用されます。前述のように制限された環境では、動的割り当てをまったく使用しないことをお勧めします。場合によっては、小さな動的割り当て用のメモリプール、またはブロックを事前に割り当てて後ですべてを破棄する「フレームベース」の割り当てを回避できます。


16

C ++コンパイラを使用することをお勧めしますが、C ++固有の機能の使用を制限します。C ++でCのようにプログラムできます(C ++を実行するときにCランタイムが含まれますが、ほとんどの組み込みアプリケーションでは、とにかく標準ライブラリを使用しません)。

先に進んでC ++クラスなどを使用できます。

  • (あなたが言ったように)仮想関数の使用を制限する
  • テンプレートの使用を制限する
  • 組み込みプラットフォームの場合は、演算子newをオーバーライドするか、メモリ割り当てにplacenewを使用する必要があります。

8
もちろん、すでに基本的にCを書いているのであれば、それを公式にすることもできます。
チャック

6
テンプレートの使用を制限するのはなぜですか?テンプレート関数は、たとえばループを展開するために、組み込みシステムで非常に役立つと思いました。
Piotr Czapla 2009年

1
テンプレートは引き続き使用できますが、出力バイナリのサイズがすぐに大きくなる可能性があるため、注意が必要です。もちろん、コードがROMなどから直接実行され、ROMスペースに余裕がある場合は確かですが、それ以外は、テンプレートの操作に注意する必要があります(各テンプレートインスタンスは基本的にすべてのテンプレートコードが再度複製されます)最悪の場合、最終的な実行可能ファイルで)。
arke

14

ファームウェア/組み込みシステムエンジニアとして、CがC ++よりも依然としてナンバーワンの選択肢である理由のいくつかを皆さんに伝えることができます。そうです、私は両方に堪能です。

1)私たちが開発している一部のターゲットには、コードとデータの両方に64kBのRAMがあるため、すべてのバイト数を確認する必要があります。はい、コードの最適化を処理して4バイトを節約し、2時間かかりました。 2008年。

2)サイズの制限があるため、すべてのCライブラリ関数は、最終的なコードに入れる前にレビューされます。そのため、divide(ハードウェアディバイダーがないため、大きなライブラリが必要です)、malloc(ヒープがないため)を使用しないことをお勧めします。 、すべてのメモリは512バイトチャンクのデータバッファから割り当てられ、コードレビューする必要があります)、または大きなペナルティを伴う他のオブジェクト指向のプラクティス。使用するすべてのライブラリ関数がカウントされることを忘れないでください。

3)オーバーレイという用語を聞いたことがありますか?コードスペースが非常に少ないため、別のコードセットと交換しなければならない場合があります。ライブラリ関数を呼び出す場合は、ライブラリ関数が常駐している必要があります。オーバーレイ関数でのみ使用する場合は、オブジェクト指向のメソッドが多すぎるため、多くのスペースが無駄になります。したがって、C ++はもちろん、Cライブラリ関数を想定しないでください。

4)ハードウェア設計が限られているため(つまり、特定の方法で配線されたECCエンジン)、またはハードウェアのバグに対処するために、キャストとパッキング(整列されていないデータ構造が単語の境界を越える場合)が必要です。暗黙のうちに想定しすぎることはできないのに、なぜオブジェクト指向が多すぎるのでしょうか。

5)最悪のシナリオ:オブジェクト指向メソッドの一部を削除すると、開発者は爆発する可能性のあるリソースを使用する前に考える必要があり(つまり、データバッファーからではなくスタックに512バイトを割り当てる)、潜在的な最悪のシナリオのいくつかを防ぐことができます。コードパス全体をテストしたり、削除したりすることはありません。

6)ハードウェアをソフトウェアから守り、コードを可能な限り移植可能にし、シミュレーションに適したものにするために、多くの抽象化を使用しています。ハードウェアアクセスは、異なるプラットフォーム間で条件付きでコンパイルされるマクロまたはインライン関数でラップする必要があります。データ型は、ターゲット固有ではなくバイトサイズとしてキャストする必要があります。直接ポインタの使用は許可されていません(一部のプラットフォームでは、メモリマップドI / Oがデータメモリと同じ)など。

私はもっ​​と考えることができますが、あなたはその考えを理解します。私たちのファームウェア担当者はオブジェクト指向のトレーニングを受けていますが、組み込みシステムのタスクはハードウェア指向で低レベルである可能性があるため、本質的に高レベルまたは抽象化可能ではありません。

ところで、私が行ったすべてのファームウェアジョブはソース管理を使用していますが、どこからそのアイデアを得るのかわかりません。

-SanDiskのファームウェア担当者。


90年代の初めに、オーバーレイは非常に人気のある手法でした(少なくともDOSの世界では)
psihodelia 2012年

良い点シン。C ++は、機能が制限され、リソースがさらに制限されているプロジェクトの電話ボックスにいる相撲取りのように感じます。

4
この答えは非常に主観的であり、具体的な理由を提供していないと思います。
Venemo 2016年

1
C ++は、必ずしも「オブジェクト指向」を意味するわけではありません。
マーティンボナーは2016

1
組み込みシステムのタスクが本質的に抽象化できないというのは、単純に真実ではありません。ポイント6)で自分で言った:「hwをswから守り、コードを可能な限り移植可能にするために、多くの抽象化を使用している」:-)ところで:「抽象化」は必ずしも「ポリモーフィズム」を意味するわけではありません。
Daniele Pallastrelli 2016

9

私の個人的な好みは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を処理するように設定されていない小さな組み込みの世界に特に当てはまります。したがって、常にasm出力を調べない限り、CとC ++は互いに同じくらい悪いというのが私の答えです。お互いに同じくらい良いです。

ヒューゴ


2
また、実際に乗算関数を呼び出すすべての命令の途中に呼び出し命令があることにも注意してください。そのコードはすべて、乗算命令でさえありません!
Rocketmagnet 2010年

マイクロに精通している人は、通常、Cコードの各部分を個別に処理する簡単な方法を知っているでしょう。まともなコンパイラーは、それよりも悪いコードを生成するべきではありません。上記の式を効率的に処理できる唯一の方法は、Cコンパイラーに適さない可能性のある仮定を行った場合です。
スーパーキャット2018年

8

埋め込まれた作業にはCを好む人もいると聞きました。これは、Cが単純であり、生成される実際のコードを予測しやすいためです。

個人的には、CスタイルのC ++(型安全性のためのテンプレートを使用)を作成することで多くの利点が得られると思いますが、そうしない本当の理由はわかりません。


+1、透明性は常に重要であり、おそらく(おそらく)制約されたデバッグツールを備えた制約された環境にとってはさらに重要です。
j_random_hacker 2009年

7

C ++の代わりにCを使用する理由はわかりません。Cでできることは何でも、C ++でもできます。VMTのオーバーヘッドを回避したい場合は、仮想メソッドとポリモーフィズムを使用しないでください。

ただし、C ++は、オーバーヘッドのない非常に便利なイディオムを提供できます。私のお気に入りの1つはRAIIです。クラスは、メモリやパフォーマンスの点で必ずしも高価ではありません。


6

IARWorkbenchでARM7埋め込みpaltformのコードをいくつか作成しました。コンパイル時の最適化とパス予測を行うためにテンプレートに依存することを強くお勧めします。ペストのような動的なキャストは避けてください。Andrei Alexandrescuの著書、Modern C ++ designに規定されているように、特性/ポリシーを活用してください。

学ぶのは難しいかもしれませんが、あなたの製品がこのアプローチの恩恵を受けることも確信しています。


5

正当な理由であり、場合によっては唯一の理由は、特定の組み込みシステム用のC ++コンパイラがまだないことです。これは、たとえばMicrochipPICマイクロコントローラーの場合です。それらは非常に簡単に作成でき、無料のCコンパイラ(実際にはCのわずかな変形)がありますが、C ++コンパイラは見えません。


1
コモコンピューティング(comeaucomputing.comは)CにコンパイルするC ++コンパイラで販売している
トーマス・L Holaday

3
Eww。そのサイトは吐き出したくなりました。
shoosh 2009年

@shoosh:はい、サイトのデザインはひどいです。ただし、コンパイラ自体は、少なくとも標準の適合性に関しては、この分野のリーダーと見なされています(パフォーマンスに関する情報はありません)。
j_random_hacker 2009年

そのウェブサイトは、私が生きている、呼吸している、そして非常に怒っているフルーツサラダの中に閉じ込められているように私を感じさせます。
ティムポスト

5

4KのRAMに制限されているシステムの場合、C ++ではなくCを使用します。これは、進行中のすべてを確実に確認できるようにするためです。C ++の特徴は、コードを一瞥するように見えるよりもはるかに多くのリソース(CPUとメモリの両方)を非常に簡単に使用できることです。(ああ、それを行うために別のBlerfObjectを作成します...おっと!メモリ不足です!)

すでに述べたように(RTTI、vtablesなどなし)C ++でそれを行うことができますが、Cで同等のことを行うのと同じくらい、C ++の使用があなたから離れないようにするために多くの時間を費やします。 。


2
あなたの最後の文は正しいですが、C ++はCに比べてバランスを崩す(かもしれない)他の利点を提供するので、無関係です。Piotrは、これらの(ゼロコスト)利点のいくつかについてすでに言及しています。
Konrad Rudolph

5

人間の精神は、可能な限り評価し、次に何に焦点を合わせることが重要かを決定し、残りを破棄または減価償却することによって複雑さに対処します。これは、マーケティング、そして主にアイコンのブランディングの背後にある全体的な基盤です。

この傾向に対抗するために、私はC ++よりもCを好みます。なぜなら、コードについて、そしてコードがハードウェアとどのように密接に相互作用しているかについて考える必要があるからです。

長年の経験から、Cは、問題のより良い解決策を考え出すことを強制するというのが私の信念です。部分的には、邪魔にならないようにし、制約を満たすために多くの時間を無駄にすることを強制しないことによって、コンパイラー作成者は良い考えだと考えました。 、または「隠れて」何が起こっているのかを理解する。

その意味で、Cのような低水準言語では、ハードウェアと優れたデータ構造/アルゴリズムバンドルの構築に多くの時間を費やしますが、高水準言語では、そこで何が起こっているのかと頭を悩ませることに多くの時間を費やします。 、および特定のコンテキストと環境で完全に合理的なことを実行できない理由。コンパイラーを打ち負かして提出する(強い型付けは最悪の犯罪者です)ことは、時間の生産的な使用ではありません。

私はおそらくプログラマーの型にうまく適合します-私はコントロールが好きです。私の見解では、それはプログラマーの人格上の欠陥ではありません。コントロールは私たちがするために支払われるものです。より具体的には、FLAWLESSLYコントロール。Cは、C ++よりもはるかに多くの制御を提供します。


ZeroMQの作者であるMartinSistrikは、なぜ今彼がC ++ではなくCでZeroMQを作成したいのかについての彼の議論でほぼ同じ点を述べました。250bpm.com/blog:8
user2548100

3

個人的には4kbのメモリを使用しているので、C ++からそれほど多くのマイレージを得ることができないと思います。言語はおそらくそれほど重要ではないので、ジョブに最適なコンパイラとランタイムの組み合わせと思われるものを選択してください。

とにかく、ライブラリも重要なので、それは言語だけではないことに注意してください。多くの場合、Cライブラリの最小サイズはわずかに小さくなりますが、組み込み開発を対象としたC ++ライブラリは削減されると想像できるので、必ずテストしてください。


2

Cは移植性で勝ちます-言語仕様のあいまいさが少ないためです。したがって、さまざまなコンパイラなど間ではるかに優れた移植性と柔軟性を提供します(頭痛の種が少なくなります)。

ニーズを満たすためにC ++機能を活用する予定がない場合は、Cを使用してください。


言語が明確であるかどうかは、以前は常識と見なされていたものを指定していると見なすかどうかによって異なりますが、最近ではそうではありません[たとえば、32ビットサイレントラップアラウンド2の補数ハードウェアのコンパイラはunsigned mul(unsigned short x, unsigned short y) { return x*y;}、製品が2147483647を超えている場合でも、または]のvoid get_float_bits(float *fp, uint32_t n) { *(uint32_t)fp = n; }値を変更する可能性があると見なす必要がある場合でも、副作用が発生しfloatます。
スーパーキャット2017年

2

非常に限られたハードウェア(4kbのRAM)向けに開発する場合、C89を使い続ける理由はありますか?

個人的には、組み込みアプリケーションに関して言えば(私が組み込みと言うとき、私はwinCE、iPhoneなどを意味するのではありません。今日の組み込みデバイスは肥大化しています)。私はリソースが限られたデバイスを意味します。私はCを好みますが、C ++もかなり使用しています。

たとえば、あなたが話しているデバイスには4kbのRAMがありますが、その理由だけでC ++は考慮しません。確かに、他の投稿が示唆しているように、C ++を使用して小さなものを設計し、アプリケーションでの使用を制限できる場合がありますが、C ++は、潜在的にアプリケーションを複雑にしたり肥大化したりする可能性があります。

静的にリンクしますか?c ++とcを使用して静的ダミーアプリケーションを比較することをお勧めします。そのため、代わりにCを検討することになります。一方、メモリ要件内でC ++アプリケーションを構築できる場合は、それを選択してください。

IMHO、一般的に、組み込みアプリケーションでは、起こっていることすべてを知りたいです。誰がメモリ/システムリソースを使用していますか、どのくらい、そしてなぜですか?彼らはいつ彼らを解放しますか?

X量のリソース、CPU、メモリなどを使用してターゲットを開発する場合、将来の要件がわからないため、これらのリソースを使用することを控えるようにします。そのため、プロジェクトにコードを追加する必要があります。単純な小さなアプリケーションであると「想定」されていましたが、最終的にははるかに大きくなります。


1
私は間違いなく2つのコンパイラを比較します。(ところで、オペレーティングシステムがないため、動的にリンクできません)
Piotr Czapla 2009年

2

私の選択は通常、使用することを決定したCライブラリによって決定されます。これは、デバイスが実行する必要があることに基づいて選択されます。したがって、9/10回..最終的にはuclibcまたはnewlibとCになります。使用するカーネルは、これにも大きな影響を与えます。または、独自のカーネルを作成している場合も同様です。

それはまた、共通点の選択です。ほとんどの優れたCプログラマーはC ++の使用に問題はありません(多くの人がC ++を使用していると不満を言っていますが)..しかし、私はその逆が真実であるとは思っていません(私の経験では)。

私たちが取り組んでいるプロジェクト(グラウンドアップカーネルを含む)では、ほとんどのことがCで行われますが、C ++を使用してネットワークを実装する方が簡単で問題が少ないため、小さなネットワークスタックがC ++で実装されました。

最終結果は、デバイスが機能して受け入れテストに合格するか、合格しないかのいずれかです。言語zを使用してxxスタックおよびyyヒープ制約にfooを実装できる場合は、それを実行し、生産性を高めるものを使用してください。

私の個人的な好みはCです。理由は次のとおりです。

  • コードのすべての行が何をしているのか(そしてコストも)知っています
  • コードのすべての行が何をしているのか(そしてコスト)を知るのに十分なほどC ++をよく知りません

はい、私はC ++に慣れていますが、標準のCと同じようにそれを知りません。

さて、その逆を言うことができるなら、まあ、あなたが知っていることを使ってください:)それがうまくいくなら、テストに合格するなど..問題は何ですか?


2
>#コードのすべての行が何をしているのか(そしてコストがかかる)コンパイラーを書いたので、それは確かではありません...優れたCコンパイラーは、物事。行ごとにコンパイルすることはありません。
jakobengblom2 2009年

@ jakobengblom2:組み込み開発では、最大のパフォーマンスよりも一貫したパフォーマンスの方が重要な場合がよくあります。コードの一部がタイミング要件を満たすかどうかを判断しようとしている場合、実際のファームウェアでは機能しない「テスト」ファームウェアで使用できる最適化をコンパイラーに採用させることは、役に立たない傾向があります。
スーパーキャット2017年

2

ROM /フラッシュはどれくらいありますか?

4kBのRAMは、実際のコードと静的データを格納するために数百キロバイトのフラッシュがあることを意味します。このサイズのRAMは変数専用である傾向があり、それらに注意すれば、コード行の点で非常に大きなプログラムをメモリに収めることができます。

ただし、C ++では、オブジェクトの実行時の構築ルールにより、コードとデータをFLASHに配置するのが難しくなる傾向があります。Cでは、定数構造体をフラッシュメモリに簡単に配置して、ハードウェア定数オブジェクトとしてアクセスできます。C ++では、定数オブジェクトはコンパイラーがコンパイル時にコンストラクターを評価することを要求します。これは、C ++コンパイラーが実行できることをまだ超えていると思います(理論的には実行できますが、実際には実行するのは非常に困難です)。 。

ですから、「小さなRAM」、「大きなフラッシュ」のような環境では、私はいつでもCを使います。非クラスベースコード用の優れたC ++機能のほとんどを備えたC99の中間的な選択肢であることに注意してください。


3
Cのフラッシュメモリに配置されるのと同じ構造体がC ++のフラッシュにも配置されない理由はありますか?C ++では構造体にコンストラクターを追加する必要はありません。
jalf 2009年

1

一般的にはありません。C ++はCのスーパーセットです。これは、特に新しいプロジェクトに当てはまります。

CPU時間とメモリフットプリントの点でコストがかかる可能性のあるC ++構造を回避することで、正しい方向に進んでいます。

ポリモーフィズムのようないくつかのものは非常に価値があることに注意してください-これらは本質的に関数ポインタです。それらが必要な場合は、賢く使用してください。

また、優れた(適切に設計された)例外処理により、組み込みアプリは、従来のエラーコードで処理するアプリよりも信頼性が高くなります。


2
C ++は、厳密に言えば、Cの厳密なスーパーセットではありませんが、その特定の詳細は、このコンテキストでは特に重要ではありません。
アラファンギオン2010

1

メモリ割り当ての問題については、Quantum Platformとそのステートマシンアプローチを使用することをお勧めします。これは、初期化時に必要なすべてのものを割り当てるためです。また、競合の問題を軽減するのにも役立ちます。

この製品は、CとC ++の両方で動作します。


1

Cコンパイラは、高度なC ++機能をサポートする必要がなく、最適化をより積極的に行うことができるため、はるかに効率的なコードを生成できると言う人もいます。

もちろん、この場合、2つの特定のコンパイラーをテストすることをお勧めします。


1
関連:restrictキーワードは、私が知る限り、C ++(およびC ++ 11)に欠落している唯一の最適化関連のC構造です。
Johan Lundberg 2012年

1

C IMHOを好む唯一の理由は、プラットフォームのC ++コンパイラが適切な状態にない場合(バギー、最適化が不十分など)です。


メモリ/リソースの使用率はどうですか?
スティーブ

それはどうですか?コードが組み込みシステムでは誰も実行しないRTTIを使用する場合を除いて、C ++コンパイラがCコードよりも効率の低いコードを生成する理由はありません。
Nemanja Trifunovic


1

C99にインラインがあります。たぶんあなたはctorsが好きかもしれませんが、dtorsを正しくするビジネスは厄介かもしれません。Cを使用しない残りの唯一の理由が名前空間である場合、私は本当にC89に固執します。これは、わずかに異なる組み込みプラットフォームに移植したい場合があるためです。後で同じコードでC ++で書き始めることができます。ただし、次の点に注意してください。C++はCのスーパーセットではありません。C89コンパイラを使用しているとおっしゃっていましたが、たとえば最初の項目はK&R以降のすべてのCに当てはまるため、このC ++とC99の比較を行います。

sizeof'a ' > 1(C ++ではなくC)。Cには、VLA可変長配列があります。例:func(int i){int a [i]。Cには、VAM変数配列メンバーがあります。例:struct {int b; int m [];}


1
いいえ。Cでは(sizeof'a ')== sizeof(int)があります。C ++では、1 == sizeof'a '
hept

1
「int * a; ...; a =(int *)malloc(size * sizeof(int));」は言うまでもありません。これは、CおよびC ++で機能するメモリを割り当てる方法であり、どちらでも使用しないでください。「a = malloc(size * sizeof(int));」のいずれかを使用します。または "vector <int> a(size);" または「int * a = new int [size];」代わりに。
デビッドソーンリー

1
私はdtorsについてあなたの主張を理解していません。それらについての全体のポイントは、彼らはあなたのコードの残りの部分はたくさん作ることでより少ない厄介。
jalf 2009年

1
+1、なぜこの投稿がこんなに悪いラップをしたのかわからない。しかし、私はjalfに同意します。デストラクタは、正しい(RAII)方法で使用すると、コードを大幅に簡素化します。(あなたは、彼らが「舞台裏の仕事」は、彼らがやっていることを言うことができる唯一の正しいコードを手動でとにかくやっているだろうとものを。)
j_random_hacker

1
私が指摘することは、質問に非常に関連していると思います。私はまた、dtorsは難しいかもしれないという私の声明に固執します、そしてその理由はまさにそれが自動的に起こるということです。私はマイナスポイントを得ました-それは本当に難解です。「はい、C ++を素晴らしい」とは言わないからだと思います。
ヘプタ

1

コンパイラによって異なります。

すべての組み込みコンパイラがすべてのC ++を実装しているわけではなく、実装している場合でも、コードの膨張を回避するのが得意ではない可能性があります(これはテンプレートでは常にリスクです)。いくつかの小さなプログラムでテストし、問題が発生するかどうかを確認します。

しかし、優れたコンパイラがあれば、いいえ、C ++を使用しない理由はありません。


1

「無制限」のリソースを持つシステムは存在しないと言いたいだけです。この世界のすべては制限されており、すべてのアプリケーションは、ASM、C、JAVA、JavaScriptのいずれであっても、リソースの使用を考慮する必要があります。「念のため」に数Mbsを割り当てるダミーは、iPhone 7、Pixel、およびその他のデバイスを非常に不安定にします。4KBでも40Gbでも。

しかし、別の側面から、リソースの浪費に反対することは、それらのリソースを節約するのにかかる時間です。すでに実装、テスト、配布されているC ++を使用する代わりに、Cで簡単なものを記述して数ティックと数バイトを節約するのに1週間余分にかかる場合。なぜわざわざ?USBハブを購入するようなものです。はい、あなたはそれを自分で作ることができますが、それはもっと良くなるでしょうか?より信頼できる?あなたがあなたの時間を数えればもっと安いですか?

ちょっと考えてみてください-あなたのコンセントからの電力でさえ無制限ではありません。それがどこから来ているのかを調べてみてください。そうすれば、ほとんどが何かを燃やしていることがわかります。エネルギーと物質の法則はまだ有効です。物質やエネルギーは現れたり消えたりするのではなく、変化します。


0

組み込み開発にISOC ++を使用する方法の例を見つけました。これは、C ++またはCを使用するたびに決定を下す人にとって興味深いものです。

それは彼のホームページでBjarneStroustrupによって提供されました

ISO C ++を本格的な組み込みシステムのプログラミングに使用する方法については、JSF航空機のC ++コーディング標準を参照してください。


まあ、飛んでいるものはギガバイトのRAMを備えたPPCプロセッサを持っている傾向があります。平均的なリソースに制約のある組み込みシステムではありません。
jakobengblom2 2009年

0

質問のさまざまな側面に対するさまざまな回答の投稿:

「malloc」

以前のいくつかの返信はこれについてかなり話します。なぜあなたはその呼びかけが存在するとさえ思うのですか?本当に小さなプラットフォームの場合、mallocは使用できないか、間違いなくオプションである傾向があります。動的メモリ割り当てを実装することは、システムの下部にRTOSを配置するときに意味がある傾向がありますが、それまでは、純粋に危険です。

あなたはそれなしで非常に遠くに行くことができます。ローカル変数用の適切なスタックすら持っていなかったすべての古いFORTRANプログラムについて考えてみてください...


0

世界中にさまざまなコントローラーメーカーがあり、それらの設計と構成に使用する必要のある命令セットを調べると、多くの問題が発生する可能性があります。アセンブリ言語の主な欠点は、マシン/アーキテクチャに依存することです。さまざまなコントローラーのコーディングを実行するために、開発者がそこに記載されているすべての指示を心から要求することは非常に大きなことです。Cは、ハードウェアに依存する詳細からアルゴリズムとデータ構造を抽象化するのに十分な高レベルであり、ソースコードをさまざまなターゲットハードウェア、アーキテクチャに依存しない言語間で移植可能にし、非常に簡単にするため、組み込み開発でCが人気を博したのはそのためです。コードを変換して維持します。しかし、C、C ++、Python、Javaなどの高水準言語(オブジェクト指向)がいくつか見られます。


0

制限と注意事項のあるC ++をお勧めします。

  1. 市場投入までの時間と保守性。C ++開発はより簡単で高速です。したがって、設計段階にある場合は、C ++を使用するのに十分なコントローラーを選択してください。(一部の大量市場では、この選択を行うことができない場合、可能な限り低コストが必要であることに注意してください。)

  2. 速度。CはC ++よりも高速ですが、速度の向上が大きくないことを確認してください。したがって、C ++を使用できます。アルゴリズムを開発してテストし、必要な場合にのみ高速化します(!)。プロファイラーを使用してボトルネックを指摘し、外部の「C」の方法で書き直して、Cの速度を実現します。(それでも遅い場合は、その部分をASMに実装します)

  3. バイナリサイズ。C ++コードはもっと大きいですが、ここに詳細を伝える素晴らしい答えがあります。特定のCコードのコンパイル済みバイナリのサイズは、CコンパイラとC ++コンパイラのどちらを使用してコンパイルされた場合でも同じになります。「実行可能ファイルのサイズは言語とはほとんど関係ありませんが、プロジェクトに含めるライブラリとは関係があります。」C ++で行くが、高度な機能を、避けるようにstreamsstringnewvirtual関数などの口コミ全てのライブラリ関数のため、サイズ制限のため、最終的なコードでそれらをさせる前(に基づいて、この答え)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.