C ++は組み込みシステムに適していますか?


167

ここと他の場所でよくある質問。C ++は組み込みシステムに適していますか?

マイクロコントローラー?RTOS?トースター?組み込みPC?

OOPはマイクロコントローラーで役立ちますか?

C ++はプログラマーをハードウェアから遠ざけすぎて効率的にしませんか?

ArduinoのC ++(動的メモリ管理、テンプレート、例外なし)を「実際のC ++」と見なすべきですか?

(うまくいけば、このwikiはこの潜在的な聖戦を封じ込める場所として役立つでしょう)


5
簡単な質問:組み込みと言うとき、マイクロコントローラーのことですか?マイクロプロセッサ?組み込みx86 /組み込みPC?
J. Polfer

1
私は聖戦を起こすつもりはなかった。その意図は、あなたの議論がそれに対して何であったかを学ぶことでした。
J.ポルファー

2
以前いくつかの質問で出てきたので、中央の場所が良いと思いました。
トビージャフィー

4
C ++対埋め込みは議論の余地のあるトピックです。私は強い意見を持っていますが、質問をして得点でプレーすることは公平だとは思いませんでした。コミュニティwikiがよりバランスの取れた議論をすることを願っています。
トビージャフィー

13
「埋め込み」は、特定の言語とそれに関連する手荷物が適切かどうかを判断する上で無意味な属性であるため、これは悪い質問です。ポイントは小規模システムと大規模システムです。小規模システムはOSを実行しておらず、メモリに制限があり、von-Neumanでなく、コールスタック、データスタックにさまざまなハードウェア制限があり、Mbを動的に割り当てることはできませんほとんどのマイクロコントローラーは「小さな」システムです。通常、シングルボードコンピューターは埋め込まれていますが、一般に「大規模」システムです。
オリンラスロップ

回答:


135

はい、C ++は組み込みシステムで引き続き有用です。他のみんなが言ったように、それはまだシステム自体に依存しています。たとえば、8ビットuCは、コンパイラがあり、一部の人々はそれをしますが(シャダー)、私の本ではおそらくノーノーでしょう。8ビットのマイクロの世界でさえ、C ++を「C +」のようなものに縮小する場合でも、C ++を使用することには利点があります。「C +」とはどういう意味ですか?つまり、new / deleteを使用しない、例外を回避する、継承のある仮想クラスを回避する、おそらく継承をすべて回避する、テンプレートに非常に注意する、マクロの代わりにインライン関数を使用constする、の代わりに変数を使用するということです#defines

組み込みシステムのCとC ++の両方で10年以上働いてきましたが、C ++に対する若々しい熱意のいくつかは、素朴さを揺さぶる現実世界の問題のために確実に消耗しました。組み込みシステムで最悪のC ++を見たことがありますが、これを「CSプログラマーがEEの世界に突入した」と呼びたいと思います。実際、これはクライアントと一緒に取り組んでいるもので、クライアントが持っているこの1つのコードベースを改善しています。

C ++の危険性は、言語と一般的なプログラミング自体で適切に教育および訓練されていなければ、腕と脚の両方を切断できる両刃の剣のような非常に強力なツールだからです。Cは片刃の剣に似ていますが、それでも同じくらい鋭利です。C ++では、非常に高レベルの抽象化を取得し、長期的には意味をなさない難読化されたインターフェイスを作成するのは簡単すぎます。これは、C ++がさまざまな言語機能(テンプレート、OOP、手続きRTTI、OOP +テンプレート、オーバーロード、インライン化)。

C ++の第一人者Scott Meyersによる、C ++の組み込みソフトウェアに関する2つの4時間のセミナーを終了しました。彼は、私がこれまで考えたことがなかったテンプレートについてのいくつかのことと、どれだけ安全性が重要なコードの作成に役立つかを指摘しました。その要点は、厳格な安全重視のコード要件を満たさなければならないソフトウェアにデッドコードを入れることはできないということです。コンパイラーはテンプレートのインスタンス化時に必要なコードのみを作成するため、テンプレートはこれを実現するのに役立ちます。ただし、リンカは常にデッドコードを最適化するとは限らないため、Cで達成するのが難しいこの機能を正しく設計するために、使用方法を徹底的に教育する必要があります。

スコット・マイヤーズは、テンプレートとインライン化の賢明な使用に関する非常に大きな支持者であり、テンプレートについて熱心であることにまだ懐疑的であると言わざるを得ません。彼は彼らが最高のツールになる場所にのみ適用されるべきだと言っているにもかかわらず、私はそれらを敬遠する傾向があります。彼はまた、C ++が、使いやすく、間違った使い方をしにくい、本当に優れたインターフェースを作成するツールを提供していると指摘しています。繰り返しますが、それは難しい部分です。これらの機能を最も効率的な方法で適用して最適な設計ソリューションにする方法を知るには、C ++の習熟レベルに到達する必要があります。

OOPについても同じことが言えます。組み込みの世界では、ランタイムポリモーフィズムのランタイムコストを処理できるかどうかを知るために、コンパイラがどのようなコードを吐き出すかを理解する必要があります。設計が納期の要件を満たしていることを証明するために、測定も行う必要があります。その新しいInterruptManagerクラスは、割り込みレイテンシを長くしすぎますか?Cでもできるリンク時ポリモーフィズムなど、あなたの問題によりよく適合するポリモーフィズムには他の形式がありますが、C ++ではPimplデザインパターン(不透明ポインター)を使用できます。

C ++は組み込みの世界でその地位を占めていると言ってもいいでしょう。あなたはそれをあなたが望むすべてを憎むことができますが、それは消えません。非常に効率的な方法で記述できますが、Cを使用するよりも正しく実行する方法を習得するのは困難です。問題を解決したり、より優れたインターフェイスを表現したりする場合は、Cよりもうまく機能することがありますが、繰り返しになりますが、自分自身を教育し、方法を学ぶことを恐れないでください。


1
これは、私が他の組み込みシステムのコンサルタントから読んだものと一致しています。私はいつも、Cを使うと、常に少しずつ自己をカットすることを教えられてきましたが、C ++のバグはよりまれになりますが、台無しにすると足を失うことになります。私が持っていない専門知識を持つ明確な回答を書いてくれてありがとう。
コルトゥク

3
EEの分野でコンピューターサイエンスの専攻が熱狂していることに注目してください。私の仕事では、私たちが持っている最悪のコードはCS専攻によって書かれました。私たちは彼にハードウェアが何であるかを教えようと永遠に過ごしました。彼はUMLを使用して構造化システムを作成し、適切な継承などを使用してJavaに基づいてシステム全体を構築しました。何かが変更されるまで機能しましたが、機能を追加したり、完全に再設計したりするのは悪いパッチ作業でした。継承によって全体をどれだけ完全に難読化したため、コードはほとんど使用できません。
Kortuk

2
あなたに噛み付くのはバグだけではなく、あなたにも噛み付くメンテナンス不能なコードです。確かに、これらのきちんとしたC ++機能を使用してプロジェクトを開始すると、すべてが泳ぎますが、2、3年後には、開発時にリファクタリングに真剣な努力が注がれなければエントロピーが作動します。それが私が今直面していることです。コードはC ++で時間の経過とともに速く腐敗します。
ジェイアトキンソン

2
UMLおよびステートマシン。あなたは本当にでミロSamekのものを検討する必要がありますstate-machine.com。彼はリファクタリングと変更が簡単な効率的なシステムを構築しましたが、それを理解するには時間がかかります。
ジェイアトキンソン

2
システムと使用可能なメモリの量に大きく依存します。RAMがほとんどない8ビットマイクロでコードを書いていますか?次に、抽象的なインターフェースに夢中になるのを避ける方が良いかもしれません。メモリのスラブを備えた32ビットの組み込みシステムのようなものを書いているなら、それを試してください。あなたは本当にそれを量る必要があります。たとえば、そのクラスに「仮想」世界を貼り付けるたびに、オブジェクトに宣言するすべてのインスタンスごとに、システムに応じて8ビット、16ビット、または32ビットの追加のポインターを取得します。あなたも気づかないでしょう、そして、男
ジェイアトキンソン

56

C ++は組み込みシステムに最適です。現在、特定のマイクロプロセッサを使用するかどうかの主要な基準として、優れた開発ツールの有無(またはその欠如)を使用しています。

リソースコストが低いため、組み込みシステムでの使用に適したC ++の領域:

  • クラス/構造の適切な使用によりもたらされるモジュール性
  • コンパイラーがテンプレートを効率的にコンパイルするのに適している場合は、テンプレート。テンプレートは、アルゴリズムをさまざまなデータ型に再利用するための優れたツールです。

OKエリア:

  • 仮想関数-以前はこれに反対していましたが、リソースコストは非常に小さく(オブジェクトごとではなく、クラスごとに1つのvtable 、オブジェクトごとにvtableへの1つのポインター、仮想関数呼び出しごとに1つの逆参照操作)、これの大きな利点いくつかの異なるタイプのオブジェクトを含む配列を持つことができるということです。オブジェクトのタイプを知る必要はありません。最近、これを使用して、それぞれが別々のメソッドを持つI2Cデバイスを表すオブジェクトの配列を作成しました。

主に小規模システムでは受け入れられない実行時オーバーヘッドのために、使用しない領域:

  • 動的メモリ割り当て-他の人はこれに言及していますが、動的メモリ割り当てを使用しないもう1つの重要な理由、タイミングの不確実性を表していることです。組み込みシステムを使用する多くの理由は、リアルタイムアプリケーションのためです。
  • RTTI(ランタイムタイプ情報)-メモリコストがかなり大きい
  • 例外- 実行速度が低下するため、明確なノーノー

入力いただきありがとうございます。興味深く、私が読んだものと非常に似ています。
Kortuk

1
実際に動的なメモリ割り当ては問題なく、時には避けられないこともあります。問題は、動的メモリの割り当て解除(およびその後の再利用)です。RTTIは記憶の独り占めです。私はそれに同意します。しかし、例外の問題は何ですか?
ウーターヴァンOoijen

1
@WoutervanOoijen:例外を除いて問題があればということでfoo通話bartry/ catchブロック、およびbarいくつかのオブジェクトとの通話を作成boz例外をスローし、システムが何らかの形のオブジェクトのデストラクタを呼び出す必要がありbarに制御を返す前に作成したがfoo。例外が完全に無効にbarされていない限り、例外がbozスローされる可能性があるかどうかを知る方法がないため、その可能性を考慮して追加のコードを含める必要があります。それに対処するために、「チェックされた例外」を備えたC ++のバリエーションを見たいと思います。例外のエスケープを許可できるルーチンの場合
...-supercat

1
...そのように宣言する必要があった場合、コンパイラがそのようなルーチンの呼び出し元に例外処理コードを含める必要があるだけです。確かに、必要な宣言をすべて追加する必要がありますが、不必要な宣言を回避することはいくらか面倒ですが、例外が有用な場所で使用され、そうでない場合はオーバーヘッドを追加できません。
-supercat

3
@WoutervanOoijen:ちなみに、ARMでこのような例外処理のためにABIを設計している場合、例外を介して終了する可能性のあるルーチンを呼び出すコードは、R14が目的の戻りアドレスの2バイト前のアドレスを指すように指定します(これは呼び出し元が16ビットワードでCALL命令に従った場合に自然に発生します)。呼び出されたルーチンは、のadd r15,r14,#2代わりに通常通り終了しますmov r15,r14; 例外を介して終了しますldrhs r0,[r14] / add r15,r14,r0。通常の出口のサイクルコストはゼロで、スタックフレームの制限はありません。
-supercat

36

はい、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よりも優れていると思う理由は次のとおりです。

  • データ隠蔽
  • より強力なタイピング/チェック
  • クラスを使用したマルチペリフェラルの透過性
  • テンプレート(常に慎重に使用する場合)
  • 初期化リスト
  • const

これらの機能はいずれも、Cの一般的な機能よりも重いものではありません。

16ビットまたは32ビットMCUに移動すると、Cのより重い機能(スタック、ヒープ、ポインター、配列、printfなど)を使用することが理にかなっています。同様に、より強力なMCUが適切になります。 C ++のより重い機能(スタック、ヒープ、参照、STL、新規/削除)を使用する。

そのため、PIC16でC ++を検討する必要はありません。言語とMCUを正しく理解していれば、両方を効果的に併用する方法がわかります。


3
これは、質問に対する非常によく表現された合理的な回答です。+1乾杯!
vicatcu

1
a[i] = b[j] * c[k];これらの変数の性質に応じて、約4ページの命令を生成できます。」MCU /コンパイラがこれを行うのは、80年代のガレージ愛好家のCPUを使用しているためです。
ランディン

@ランディン-ため息。いいえ、スタックインデックスのような複雑なものを持たないように、できるだけ小さく、できるだけ安くなるように設計された安価な小さなMCUを使用していることを意味します。
Rocketmagnet

2
@Rocketmagnetおそらく1990年代に?最近では、くだらない8ビターは32ビターと同じ価格で販売されています。前者を選ぶ理由は、消費電流だけです。また、スタックのない非常に安っぽい8苦味については、このような限られたMCUのアセンブラーの代わりにCを記述すると、間違っている可能性があります。生成された4ページは、CPUにとって非常に複雑なプログラムを記述するためのあなた自身の過失であり、本質的にCはタスクにとって間違ったツールです。(私は過去にFreescale RS08でこれを行いましたが、それは非常に馬鹿げたアイデアでした。)
ランディン

@Lundin 32ビットプロセッサは、16ビットより高速である必要はありません。これは、PCの世界で16ビットから32ビットへのプログラムの移行が行われていた時代にさかのぼります。
バーリーマン

24

私はいつもこれらの議論が楽しく読めると思います。さまざまな利用可能な言語の長所と短所についての知的議論についてはそれほどではありませんが、通常は仕事/経験/関心のある分野に基づいてトピックに関する誰かのスタンスを固定することができます。CSメジャーとメンテナンスプログラマがクヌースを左右に引用し、パフォーマンスが重要な現実の世界で働いている人がすべて狂っていると思うのは、「時期尚早な最適化」の議論があります(私は後者のグループのメンバーです)公平であるために)。

1日の終わりに、CまたはC ++で優れたソフトウェアを開発するか、ここに言語を挿入できます。それは、言語ではなく開発者の能力にかかっています。通常、言語の専門家である必要があるのは、最初に間違った言語を選択し、それを問題解決にワープする必要がある場合のみです。ほとんどの場合、これらは曖昧な機能またはコンパイラーに飛び込む必要がある唯一の状況です目標を達成するためのトリック。

私はよく、これらの議論を「私は言語Xと何とか専門家だ」と始めると聞きます。正直に言って、私はすぐにこれらの人々の信用を失います。ツールを使用して問題を解決し、それがいかに「クール」であるかを示したいという欲求によって。

開発者が最初にツールセットを選択し、次にそれを問題に合わせようとするのをよく見ます。

別の答えへのコメントで述べたように、これらの言語戦争はしばしば、言語Xがプログラマーにもっと馬鹿げたことをさせると主張するようになります。読むのは楽しいですが、これらすべてのステートメントは、あなたが良い開発者を雇う問題を抱えており、悪い開発者を雇い続け、できるだけ少ないことができるようにツールを選択することで状況を支援しようとするのではなく、その問題に直接対処する必要があることを本当に意味します可能な限り損傷します。

私の意見では、優れた開発者は、ソフトウェア開発であれハードウェア開発であれ、問題を調査し、ソリューションを設計し、「最良の方法」でソリューションを表現できるツールを見つけます。必要なツールが以前に使用したことがないものであっても、新しいツールを選択するプロジェクトに3〜4の言語/開発ツールを使用した後は、開発時間に最小限の影響しかありません。

もちろん、「最善の方法」は主観的な用語であり、研究段階でも定義する必要があります。目の前の問題に基づいて、パフォーマンス、表現の容易さ、コード密度など、多くの問題を考慮する必要があります。適切なツールを選択し、問題を理解するために時間を割いて「無料で」提供する必要がある場合は、理由のためにそのリストに保守性を含めませんでした。コードの維持が難しいのは、多くの場合、間違ったツールを選択したか、システム構造が貧弱なためです。これにより、コードを機能させるためのいハックが発生します。

特定の問題を定義することなく、他の言語よりも「良い」と主張するのはばかげています。オブジェクト指向のアプローチは、機能的なアプローチよりも常に優れているとは限りません。オブジェクト指向の設計パラダイムに非常に役立ついくつかの問題があります。そうでないものはたくさんあります。人々がハーピングを楽しんでいると思われる多くの言語機能について同じ声明を出すことができます。

実際にコードを入力する問題に20%以上の時間を費やしている場合は、おそらく非常に貧弱なシステムを開発しているか、非常に貧弱な開発者がいます(またはまだ学習中です)。ほとんどの時間を前もって問題を図式化し、アプリケーションのさまざまな部分がどのように相互作用するかを判断する必要があります。才能のある開発者のグループをマーカーボードと解決すべき問題のある部屋に貼り付けて、システム全体に満足するまでコードの記述やツールの選択を許可しないように伝え、システムの品質を向上させます開発時間の改善が保証された最新の新しいツールを選択するよりも、出力と開発速度が向上します。(スクラム開発を、私の議論とは反対の極の参照として調べてください)

多くの場合、多くの企業は開発者の価値を、書かれた行の数、または「目に見える出力」を見ることによってしか測定できないという現実がしばしばあります。彼らは、マーカーボードがある部屋での3週間を生産性の低下と見なしています。開発者は多くの場合、開発の「思考」段階をスピードアップすることを余儀なくされるか、社内の政治的問題によって設定されたツールを使用せざるを得ません。 。さらに悪いことに、適切な市場調査を行うことができないか、変更が開発サイクルに与える影響を理解していないため、会社から絶えず変化する一連の要件を取得します。

この暴言で少し話題から外れてすみません、私はこの話題について非常に強い意見を持っています。


2
現在、特定の組み込みシステムでは、アプリケーションレベル(ドライバーより上)で単体テストをノックしていません。開発段階の早い段階で単体テストとバグの根絶の即時フィードバックの価値はありますが、デザインを生み出すためのTDDパラダイム全体が少し頭が痛いようです。コーディングを開始する前に、問題について「考え」、頭の中で、紙の上で、またはホワイトボードの上でそれを図式化するのに時間をかけるのが好きです。また、TDDは、市場が要件の先行調査を行わないよう奨励していると考えています。
ジェイアトキンソン

2
そして、私の非常に長いコメントに最後の注意を置くために..デザインを行うのに言語の専門家は必要ありません。言語を扱うことができる専門のデザイナーが必要です。
ジェイアトキンソン

1
PRD =製品要件ドキュメント、MRD =マーケティング要件ドキュメント、TRD =技術要件ドキュメント。TDD =テスト駆動開発。
ジェイアトキンソン

1
@Mark-デザインの前向きな感情に同意しますが、それは一点に過ぎません。a)要件がかなり安定/既知であり、b)設計を行っている開発者が経験を積んでいる場合、事前の重い設計作業は報われると思います。前の 仕事、私はデザインをすることを任されました、そして、それは私のチームリーダーによってかなりタイムボックス化されました、そして、私は考えました、「何をすべきか馬鹿げています!しかし、コーディングの過程で、私は探すことを知らなかった多くのことを発見しました。私が多くの設計を行い、コード時間を最小限に抑えていたら、それは無駄でした。JME。
J.ポルファー

1
@sheepsimulator 2番目の点に明らかに同意します。リードシステムアーキテクトは経験豊富な開発者だと思います。最初の点で、私は実際に同意しません。要件の変更が予想されるほど、設計段階で費やす時間を増やす必要があります。なぜなら、優れた、変更しやすい設計を作成する必要があるからです。いくつかの哲学が急速な発展を提案していることを知っています。場合によっては、これは多くの悪いプログラマーや経験の浅いプログラマーのようにうまく機能します。これらすべての設計哲学は、「柔軟なシステムを設計する祈りはないので、試して時間を無駄にしない」と言っています。
マーク

17

どの言語でも組み込みシステムに適しています。組み込みとは、無料のコンピューターとは対照的に、より大きな装置の一部を意味します。

(ハード)リアルタイムまたは限られたリソースのシステムを求められたとき、質問はより関連性があります。

リアルタイムシステムの場合、C ++は最も厳しい言語の1つであり、厳しい時間の制約のためにプログラミングする場合に適切です。ヒープの使用(無料の演算子)を除き、実行時間が不定の構造はないため、プログラムがタイミング要件を満たしているかどうかをテストでき、さらに経験を積むと予測することもできます。もちろん、新しい演算子を1回限りの割り当てに使用することはできますが、ヒープの使用は避けてください。C ++がCを介して提供する構成は、組み込みシステム(OO、例外、テンプレート)で有効に使用できます。

非常にリソースに制限のあるシステム(8ビットチップ、数KB未満のRAM、アクセス可能なスタックなし)では、完全なC ++は不適切な場合がありますが、それでも「より良いC」として使用される場合があります。

残念なことに、Adaは一部のニッチでしか使用されていないようです。多くの点でPascal ++ですが、すでに深刻な混乱を招いた言語との上位互換性の負担はありません。(編集:深刻な混乱はもちろんCです。パスカルは美しいですが、やや非現実的な言語です。)

================================================== ===============

編集:私はこの質問を参照して閉じられた新しい質問(「マイクロコントローラーをプログラミングしているときにC ++が必要な場合は?」)への回答を入力していたので、私が書いたものを追加します:

を使用することの全面的な理由はありませんプログラミング言語をが、特定の状況で多少の重みを持つ引数が存在する可能性があります。これに関する議論は多くの場所で見つけることができ、「マイクロコントローラーにC ++を使用しない」から「C ++を常に使用する」までの範囲の位置を取ります。私は最後のポジションにもっといます。いくつかの議論をすることはできますが、特定の状況(およびどの方向)でどれだけの重量を運ぶかを自分で決める必要があります。

  • C ++コンパイラは、Cコンパイラよりもまれです。一部のターゲット(たとえば、12ビットおよび14ビットのコアPIC)には、C ++コンパイラがまったくありません。
  • (良い)C ++プログラマーは(良い)Cプログラマーよりもまれです。特に、電子工学の(やや)知識があるプログラマーの間では珍しいです。
  • C ++には、小規模システム(例外、RTTI、ヒープの頻繁な使用など)に適さないCよりも多くの構造があります。
  • C ++にはCよりも豊富な(標準)ライブラリのセットがありますが、前のポイントの結果は、C ++ライブラリがしばしば小規模システムに不適切な機能を使用するため、小規模システムでは使用できないことです。
  • C ++にはCよりも多くの構成体があり、自分で足を撃てます。
  • C ++には、Cよりも多くの構成体があり、それを防ぐことができます自分で足を撃てます(はい、IMOこれと前のものは両方とも真実です)。
  • C ++には、より豊富な抽象化メカニズムのセットがあるため、特にライブラリに対して、より優れたプログラミング方法が可能になります。
  • C ++言語の機能(たとえば、コンストラクタ/デストラクタ、変換関数)により、コード全体を見て、生成されたマシンを見るのが難しくなり、言語コンストラクトのスペースと時間のコストがかかります。
  • C ++言語の構造体は、「正しいこと」をより抽象的な方法で行うため、これらがマシンコードにどのように正確に変換されるかを意識する必要が少なくなります。
  • C ++言語標準は急速に進化しており、大手コンパイラ(gcc、clang、microsoft)によって迅速に採用されています。Cはかなり進化しており、いくつかの新しい機能(バリアント配列)の採用は怖く、後の標準で元に戻されています。特にこの点は、異なる人々が反対の立場をサポートするためにそれを使用するという点で興味深いです。
  • C ++は間違いなくCよりもシャープなツールです。プログラマー(または自分)がそのようなツールを使用して美しい彫刻を作成することを信頼していますか、それとも自分自身を傷つけることを恐れて、あまり美しくないがリスクの低い製品に落ち着くでしょうか? ?(彫刻教師がかつて私に、鈍器は鋭い道具よりも危険な場合があると言っていたことを思い出します。)

私のブログには、小さなシステム(=マイクロコントローラー)でのC ++の使用に関する記述があります。


15

私の経験では、C ++は通常、小規模な組み込みシステムには適していません。つまり、マイクロコントローラーとOSのないデバイスです。

多くのC ++ OOPテクニックは、動的メモリ割り当てに依存しています。これは、小規模なシステムではしばしば欠落しています。

STLとBoostは、C ++の力を実際に示しています。どちらもフットプリントが巨大です。

C ++は、制約のあるシステムでは受け入れなければならないマシンを抽象化するようにプログラマーに推奨します。

昨年、私は商用のリモートデスクトップ製品を携帯電話に移植しました。C ++で記述され、Windows、Linux、およびOSXで実行されました。ただし、STL、動的メモリ、およびC ++例外に大きく依存していました。WinCE、Symbian、およびOSのない環境でそれを実現するには、Cの書き換えが最も賢明なオプションでした。


小規模システムに関しては同意しますが、小規模システムにはさまざまな定義があると思います。1kBのROMがあり、よく書かれたCコードが1バイトを除くすべてのROMを使用する場合、それは小さなシステムです。
Kortuk

6
Cのフットプリントを小さくすることはできないと主張しているわけではありませんが、C ++をまだ使用して、今説明したものの設計に非常に似た結果を得ることができました。問題は、ほとんどのOOPプログラマーがダイナミックメモリを備えたシステムに慣れており、非常に非効率的な構造を使用しているため、低電力システムではまったく役に立たないコードになることです。
コルトゥク

4
あなたの言っていることは、C ++を使用したくない、CとC ++の間で何かを使用したいということです(単にC +と呼びますか?)。その場合、私は同意します、C ++の人々が使用するという理由でたくさんのがらくたがあります。ほとんどすべての言語は、優れた高速コードを生成できます。その使用方法は問題です。P:言語で最も神聖な戦争は、言語能力の結果が、それは本当にばかげた議論をさればかげたことをする馬鹿のためのがいかに簡単かを超える引数ではありません
マーク・

2
「言語に対するほとんどの神聖な戦争は、言語の能力の結果ではなく、馬鹿がばかげたことをするのがどれほど簡単かという議論です。これは本当にばかげた議論です。」とても楽しい文章でした。私はあなたの姓が必要なので、それを引用できます。
Kortuk

1
私は実際にはCの動的メモリも使用しません。私が持っている場所はありません。長期的に見て、非常に細分化されて問題を引き起こし始める可能性があることを読みました。メモリ不足の場合は、非常に明確に設計されたケースが必要であり、残りの量を正確に監視できる必要があります。
Kortuk

11

ベアメタルおよびリソースに制約のあるシステムでのC ++に関するこの議論に、熱よりも多くの光を追加したいと考えています。

C ++の問題:

  • 例外は特にRAMの問題です。これは、必要な「緊急バッファ」(メモリ不足の例外が発生する場合など)が使用可能なRAMよりも大きくなる可能性があり、マイクロコントローラの無駄であることは確かです。詳細については、n4049およびn4234を参照してください。それらはオフにする必要があります(これは現在指定されていない動作ですので、確実にスローしないでください)。SG14は現在、これを実現するためのより良い方法に取り組んでいます。

  • RTTIはおそらくオーバーヘッドに見合う価値がないため、オフにする必要があります

  • 大規模なデバッグビルド。ただし、これは従来のデスクトップ開発では問題ではありませんが、デバッグがチップに収まらない場合は問題になる可能性があります。問題は、テンプレートコードまたは明確にするために追加された追加の関数呼び出しから発生します。これらの余分な関数呼び出しはオプティマイザーによって再び削除され、追加された明快さまたは柔軟性は大きな利点となりますが、デバッグビルドではこれが問題になる可能性があります。

  • ヒープ割り当て。STLではカスタムアロケーターの使用が許可されていますが、これはほとんどのプログラマーにとって複雑になる可能性があります。ヒープ割り当ては非決定的(つまり、リアルタイムではない)であり、断片化は、テストで作業したにもかかわらず予期しないメモリ不足の状況を引き起こす可能性があります。空き領域とさまざまなサイズを追跡するためにヒープに必要なブックキーピングは、小さなオブジェクトでは問題になる可能性があります。通常はプール割り当て(CとC ++の両方)を使用する方が適切ですが、ヒープのみを使用するC ++プログラマにとっては異常な場合があります。

  • ランタイムポリモーフィズムやその他の間接的な呼び出しは、通常、パフォーマンスに大きな影響を与えます。オプティマイザーは、実際のフェッチやアドレスへのジャンプ以上にそれらを見ることができないため、問題は通常より大きくなります。この理由から、CおよびC ++では間接呼び出しを避ける必要がありますが、C ++の場合と同様にカルチャに深く染み込んでいます(他のドメインでも非常に便利です)。

  • clibとの暗黙的なインターフェースには問題があります。clibの問題がC ++カテゴリにあるのは直観に反するかもしれませんが、問題は並行環境でのリソースの暗黙的な共有から発生します(Cでは共有がより明示的です)。一般的なnewLib実装の使用は、uCでは通常必要ない多くの肥大化を招くことがありますが、newLibNannoはリエントラントではないので、アクセスをシリアル化する必要があります(ここでは簡単に説明します)。これはCにとっても問題ですが、アクセスはより明確です。経験則として、基本的にISRコンテキストのネームスペースstdの何も、clibの状態(errornoやヒープなど)にアクセスしないことが確実でない限り使用しないでください。スレッド(私はRTCを好む)を使用してnewとdeleteをオーバーライドし、mallocとfreeへのアクセスを同期する場合にも重要です。

結論として、C ++にはいくつかの問題がありますが、本質的にはすべて修正可能または回避可能です。

Cの場合、問題は高次です。コンパイル時に最適化を実行したり、不変条件をチェックしたりする方法で物事を抽象化するCの構文能力はありません。したがって、ユーザーがそれらを使用するためにそれらがどのように機能するかを知る必要がない方法で物事を適切にカプセル化することはできず、私のエラー検出のほとんどは実行時に行われます(遅すぎるだけでなくコストもかかります)。基本的に、Cでジェネリックにする唯一の方法はデータを使用することです。たとえば、実行時に評価されるフォーマット文字列をprintfまたはscanfに渡します。そのため、コンパイラが正しいデータを渡したときに理論的に可能なオプションの一部を使用していないことを証明するのは非常に困難です。つまり、潜在的なデッドコード生成と最適化の可能性の損失を意味します。

私はここでシットストームを解き放つかもしれないことを知っていますが、32ビットマイクロコントローラでの私の経験は、両方の専門家によって書かれたCとC ++の比較です(C ++は高度にテンプレート化されている可能性があります)C ++はすぐにはるかに効率的な言語ですどんなものでも(ライブラリのように)すべてジェネリックである必要があり、ジェネリックでない場合でも基本的に同等です。また、初心者にとっては、C ++のエキスパートライブラリ実装者の専門知識を活用するのも簡単です。

同時に、実際には、入力がintではなく、誤ったデータを渡すことができない関数が実際にはほとんどありません。 something表現の方法としてintを使用しているため間違っています(無効な値または「何か」ではなく「otherThing」を渡します)。Cでは、ユーザーが間違っているかどうかを確認する唯一の方法は実行時です。C ++では、すべてのチェックではなく、コンパイル時にいくつかの無料のチェックを実行できます。

結局のところ、Cチームは最も弱いプログラマーと同じくらい強力であることが多く、結果として得られるコードの利点は、マルチプレイヤー1またはパフォーマンスペナルティのいずれかです。これが意味することは、ユニークなデザイン決定のユニークな環境で唯一のユニークなジョブの高いパフォーマンスであるか、複数の環境で使用するのに十分な汎用性があることです(他のマイクロコントローラー、他のメモリ管理戦略、他のレイテンシー対。スループットのトレードオフなど))が固有のパフォーマンスコストがあります。

C ++では、専門家によって物事をカプセル化でき、コンパイル時のコード生成が特定のタスクに適応し、静的チェックによりユーザーがバカなことをゼロコストで実行できない多くの環境で使用できます。ここでは、汎用性と高速性のトレードオフがはるかに少ないため、最終的にコスト対利益の観点から、パフォーマンス、安全性、生産性が向上します。

組み込み用の優れたC ++ライブラリがまだ十分に不足していることは有効な批判です。これにより、C ++コンパイラでほとんどCを使用するという実用的な決定につながる可能性があります。プロジェクトでCのみを使用するという決定は、基本的にはイデオロギーに基づいており、レガシーサポートの必要性や、C ++では実行できるがCでは実行できない非常に厳選された一連の愚かなことを控えるチームの規律がないことを認めている同時に、Cでは保護できないがC ++ではできる、はるかに大きな愚かなことをしないように十分に規律を定めました。


私の答えへの素晴らしい追加:)この神秘的なC ++の恋人は誰でしょうか?彼のプロフィールは「どうやら、このユーザーは彼らについて謎の空気を保つことを好むようだ」と述べている。(悪い英語、BTW)しかし、AHAの場所は「ボーフム、ドイツ」です.....会議でお会いしましょう!
ウーターヴァンOoijen

ああ、ええ、私のプロフィールを更新しました;)素敵なあなたは、EMBOに来て知っている++、それは良い群衆になります
odinthenerd

10

私の経歴: ベル研究所の古いプログラマーのもとでの学校外でのトレーニング。学部研究プロジェクトで2年間、2年間働いています。VB.NETのデータ収集/プロセス制御。VB6でエンタープライズデータベースアプリケーションの作業に1.5年を費やしました。現在、2GBのストレージ、512MBのRAM、500MHz x86 CPUを備えた組み込み PCのプロジェクトに取り組んでいます。同時に実行されるいくつかのアプリは、C ++で記述され、その間にIPCメカニズムがあります。はい、私は若いです。

私の意見:が上で書いた環境を考えると、C ++は効果的に機能すると思います。確かに、ハードリアルタイムパフォーマンスは、私が使用しているアプリの要件ではなく、一部の組み込みアプリケーションでは問題になる可能性があります。しかし、私が学んだことは次のとおりです。

  • C ++はCと根本的に異なります(つまり、C / C ++はありません)。有効なCはすべて有効なC ++ですが、C ++は非常に異なる言語であり、CではなくC ++でプログラムする方法を学習して、あらゆる状況で効果的に使用する必要があります。C ++では、手続き型ではなく、オブジェクト指向でプログラミングする必要があり、2つのハイブリッド(多くの関数を持つ大きなクラス)ではありません。一般に、機能の少ない小さなクラスの作成に焦点を合わせ、すべての小さなクラスを一緒に大きなソリューションに構成する必要があります。私の同僚の一人は、私はオブジェクトで手続き的にプログラムを作成していたことを説明してくれました。よりオブジェクト指向の手法を適用し始めたとき、コードの保守性/可読性が向上したことがわかりました。

  • C ++は、オブジェクト指向開発の形で追加機能を提供します。これにより、コードを簡素化して読みやすく、保守しやすくすることができます。正直なところ、OOPを実行する際のパフォーマンス/スペース効率の改善方法はあまりないと思います。しかし、OOPは複雑な問題を多くの小さな断片に分割するのに役立つテクニックだと思います。そして、それは、このプロセスの要素であり、無視すべきではないコードで作業している人々にとって役立ちます。

  • C ++に対する多くの議論は、主に動的メモリ割り当てに関係しています。Cにも同じ問題があります。オブジェクト指向アプリケーションは、動的メモリを使用せずに作成できますが、オブジェクトを使用する利点の1つは、これらを動的に簡単に割り当てることができることです。Cと同じように、メモリリークを減らすためにデータを管理する方法に注意する必要がありますが、RAII手法はこれをC ++で簡単にします(動的メモリをオブジェクトにカプセル化することで自動的に破壊します)。すべてのメモリの場所が重要な一部のアプリケーションでは、これは管理するにはあまりにもワイルドで毛深いかもしれません。

編集:

  • WRTの「Arduino C ++」の質問:動的メモリ管理のないC ++が依然として有用であると主張します。コードをオブジェクトに整理してから、それらのオブジェクトをアプリケーション内のさまざまな場所に配置したり、コールバックインターフェイスを設定したりできます。C++で開発しているので、スタックはオブジェクトに対しても有用です。私は認めますが、Arduino用の組み込みアプリを実際に書いたことはないので、私の主張の裏には証拠がありません。今後のプロジェクトでArduinoの開発を行う機会があります-願わくば、そこで自分の主張をテストできるといいのですが。

2
2番目の点についてコメントしたいと思います。それは、複雑な問題を多くの小さな断片に分割するのに役立ち、その機能は無視されるべきだということです。これが私がプロC ++だという正確な理由です。プログラミングに関する非常に多くの研究は、プログラムのサイズが直線的に増加すると、開発時間が指数関数的に増加することを示しています。これは逆の方法に従います。プログラムを適切に分割できれば、開発時間を指数関数的に減衰させることができます。これが断然最も重要なことです。
Kortuk

2番目の点についても同様です。単にOOP設計手法を使用しても、区画化されたコードは生成されません。優れた基本設計があれば、その設計をどのように表現するかは開発者に任されます。OOPは、コードを適切に分離することを定義せず、別のオプションを提供します。さらに、そのようにした外観を提供しますが、良いデザインを強制するものではありません。
マーク

それは常に真実です。良いデザインを強制する言語を聞いたことがありません。ほとんどの場合、それは開発者の仕事であり、C ++を使用すると組織化された方法で簡単に実装および実装できるようになると思います。
-Kortuk

@マーク-同意します。それは私にとって学習プロセスでした。
J. Polfer

7

はい、C ++の問題はコードのフットプリントの増加です。

一部のシステムではバイトをカウントしていますが、その場合、システムの境界に近い実行コストを受け入れなければならないため、Cの開発コストが増加します。

しかし、Cでさえ、適切に設計されたシステムでは、すべてをカプセル化しておく必要があります。適切に設計されたシステムは難しく、C ++はプログラマーに非常に構造化され制御された開発方法の場を提供します。OOPを学習するにはコストがかかります。OOPに切り替える場合は、それを受け入れます。多くの場合、管理者はCを続行し、コストを支払わない方がよいでしょう。切り替えの結果を測定するのは難しいためです。生産性が向上します。組み込みシステムの第一人者であるJack Ganssleによる記事は、こちらをご覧ください

動的メモリ管理は悪魔です。実際には、悪魔は自動ルーティングであり、動的なメモリ管理はPC上でうまく機能しますが、少なくとも数週間ごとにPCを再起動することを期待できます。組み込みシステムが5年間動作し続けると、動的メモリ管理が本当に台無しになり、実際に失敗し始めることがわかります。Ganssleは、彼の記事でスタックやヒープなどについて説明しています。

C ++には、問題を引き起こしやすく、多くのリソースを使用する傾向があるものがいくつかあります。動的メモリ管理とテンプレートの削除は、C ++のフットプリントをCのフットプリントに近づけるための大きなステップです。これはまだC ++です。優れたC ++を作成するためのメモリ管理またはテンプレート。例外が削除されたことに気づかなかったので、リリースで削除したコードの重要な部分は例外であると考えていますが、その時点まで使用しています。フィールドテストでは、例外がキャッチされたことを通知するメッセージを生成することができます。


1
以前はコードフットプリントが問題であることに同意していましたが、最近では、フラッシュサイズがマイクロコントローラーの価格に非常に小さな影響を及ぼし、RAMサイズやIOピンの数よりもはるかに少ないようです。
ウーターヴァンOoijen

ダイナミックメモリに関する議論は、より重要なIMOです。私は数週間連続して稼働できる産業用システムを見てきましたが、診断層(C ++で記述されている)により、再起動の時間が約12時間に制限されます。
ドミトリーグリゴリエフ

6

Linus Torvaldsによるこの反C ++の暴言は面白いと思いました。

C ++の絶対的な最悪の機能の1つは、多くのことをコンテキスト依存にする方法です-つまり、コードを見ると、ローカルビューは単に何が起こっているかを知るのに十分なコンテキストをほとんど与えないことを意味します。

彼は組み込みシステムの世界についてではなく、Linuxカーネルの開発について語っています。私にとって、関連性はこれに由来します.C ++にはより大きなコンテキストを理解する必要があり、オブジェクトテンプレートのセットを使用することを学ぶことができます。数か月後にコードを更新する必要があるときにそれらを覚えているとは信じていません。

(一方で、Python(C ++ではなく、同じOOPパラダイムを使用)を使用する組み込みデバイスで現在作業を行っていますが、これはまさにその問題を抱えています。私の防御では、PCと呼ばれるほど強力な組み込みシステムです。 10年前。)


5
私たちは異なるかもしれませんが、プロジェクトを開いただけではすぐに何が起こっているのかわかりませんが、それが何をしているのかを知っていて、Cでよくコード化されたものとC ++でコード化されたものがある場合、C ++は常にもっとクリア。Cで適切に開発するには、カプセル化を実装する必要がありますが、C ++を使用すると非常に簡単になります。クラスを適切に使用すると、インターフェイスの場所が非常に明確になり、オブジェクトを介して完全に処理できます。
Kortuk

カプセル化とクラスについて完全に合意しました。演算子のオーバーロードと継承、それほどではありません。
pingswept

1
ハハ、はい、演算子のオーバーロードを使用してコードの機能を難読化することができます。誰かがオペレーターの過負荷になっている場合、明確な理由のためであるか、まったく行われていない必要があります。継承は、いくつかの追加を加えて親と同じようなことを実際に実行している特定の場合にのみ使用してください。私は、OOPですべての関数を使用するとは限りません。私は両方を使用しましたが、組み込みシステムでは、私がそうするケースを考えることができません。私が思うに、変数名に80文字の制限があるコンパイラーはすぐに廃棄されるべきです。
コルトゥク

2
私はPythonでMCUをプログラミングすることを考えて口の中に少し投げ入れました
...-vicatcu

あなただけではありませんが、それがうまく機能し、効率的であれば、私は許すことができます。
Kortuk

6

賛否両論と決定要因については、他の回答がかなり良いケースになったと思うので、要約していくつかのコメントを追加したいと思います。

小型マイクロコントローラー(8ビット)の場合、方法はありません。あなたは自分自身を傷つけようとしているだけで、利益はなく、あまりにも多くのリソースをあきらめます。

まともなOSを搭載したハイエンドマイクロコントローラー(たとえば、32ビット、RAM、ストレージ用に10メガバイトまたは100メガバイト)では、完全に問題ありません。

質問は次のとおりです。境界はどこですか?

確かなことはわかりませんが、C ++で1 MBのRAMと1 MBのストレージを備えた16ビットuC用のシステムを開発したら、後悔するだけです。はい、うまくいきましたが、私が持っていた余分な仕事は価値がありませんでした。私はそれを適合させ、例外のようなものがリークを発生させないようにしなければなりませんでした(OS + RTLサポートはかなりバグが多く、信頼性がありませんでした)。さらに、OOアプリは通常、多くの小さな割り当てを行い、それらのヒープオーバーヘッドは別の悪夢でした。

その経験を考えると、将来のプロジェクトでは、少なくとも16ビットのシステムで、RAMとストレージ用に少なくとも16 MBのC ++のみを選択すると想定しています。これは任意の制限であり、おそらくアプリケーションの種類、コーディングスタイル、イディオムなどによって異なります。ただし、警告を考えると、同様のアプローチをお勧めします。


2
私はここで意見を異にする必要があります。システムリソースのためにC ++が受け入れられるようになる突然のポイントではありません。これにより、同じスペースを取るOOPデザインのコードが作成されます。貧弱に書かれたCも同様に悪い場合があります。
-Kortuk

1
それは、アプリケーションの大きさと、より多くのスペースを必要とする特定の機能(テンプレートや例外など)の使用量に依存します。しかし、個人的には、抑制されたC ++に制限するよりも、Cを使用したいです。しかし、それでも大きなRTL、仮想メソッドサンク、コンストラクター/デストラクタチェーン呼び出しのオーバーヘッドが発生します...これらの影響は慎重なコーディングで軽減できますが、C ++の使用、抽象化、高レベルの視点。
-fceconel

4

組み込みシステムで役立つC ++の機能がいくつかあります。例外など、他にもコストがかかる可能性があり、そのコストが常に明らかになるとは限りません。

私が自分の娘を持っているなら、両方の長所を組み合わせた人気のある言語があり、両方の言語に欠けているいくつかの機能が含まれていました。一部のベンダーはそのような機能をいくつか備えていますが、標準はありません。私が見たいいくつかのこと:

  1. 例外をスローまたはリークする可能性のある関数を宣言する必要があるJavaに似た例外処理。このような宣言の要件はプログラミングの観点からはやや面倒かもしれませんが、関数が成功した場合に任意の整数を返す可能性があるが失敗する可能性がある場合には、コードの明瞭さを改善します。多くのプラットフォームは、たとえば、レジ​​スタに戻り値を持ち、キャリーフラグに成功/失敗を示すことにより、コードでこれを安価に処理できます。
  2. 静的およびインライン関数のみのオーバーロード。私の理解では、Cの標準化団体は、関数のオーバーロードを回避して、名前のマングリングの必要性を回避しました。静的関数およびインライン関数のオーバーロードを許可すると、その問題が回避され、外部関数のオーバーロードの利点の99.9%が得られます(.hファイルは、異なる名前の外部関数に関してインラインオーバーロードを定義できるため)
  3. 任意または特定のコンパイル時解決可能な定数パラメーター値のオーバーロード。一部の関数は、定数値で渡されると非常に効率的にインライン化できますが、変数が渡されるとインライン化が非常に悪くなります。他の場合、値が定数の場合に最適化される可能性のあるコードは、そうでない場合はペシミゼーションになる可能性があります。例えば:
    インラインvoid copy_uint32s(uint32_t * dest、const uint32_t * src、__is_const int n)
    {
      if(n <= 0)return;
      else if(n == 1){dest [0] = src [0];}
      else if(n == 2){dest [0] = src [0]; dest [1] = src [1];}
      else if(n == 3){dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2];}
      else if(n == 4){dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2]; dest [3] = src [3];}
      else memcpy((void *)dest、(const void *)src、n * sizeof(* src));
    }
    
    コンパイル時に「n」を評価できる場合、上記のコードはmemcpyを呼び出すよりも効率的ですが、「n」をコンパイル時に評価できない場合、生成されるコードは単純にコードよりもはるかに大きく、遅くなりますmemcpyと呼ばれます。

C ++の父親は組み込み専用バージョンのC ++にはあまり熱心ではないことは知っていますが、Cを使用するだけでかなりの改善が得られると思います。

上記のようなものがあらゆるタイプの標準について検討されているかどうかは誰でも知っていますか?



@Joby Taffey:私は自分の投稿を編集して、C ++の作成者が埋め込みサブセットに熱心ではなかったという言及を省略したと思います。私は努力があったことを承知していますが、私の理解では、彼らはそれほど遠くまでは行きませんでした。8ビットプロセッサに対応できる標準化された言語が確実に使用され、上記のような機能はどのプラットフォームでも役立つと思います。上記の#3のようなものを提供している言語を聞いたことがありますか?これは非常に便利に思えますが、どの言語でも提供されるのを見たことはありません。
スーパーキャット

「C ++の父」は組み込みシステムプログラミングの経験がないのに、なぜ彼の意見を気にする人がいるのでしょうか。
ランディン

@Lundin:影響力のある人々がさまざまな問題について彼の意見を気にしているように見えるという事実は、他の人々がそうする理由そのものであるように思われます。上記を書いたので、テンプレートの力が高まると、コンパイル時に解決できる定数に基づいてオーバーロードを持つ新しい可能性が追加されたかもしれませんが、そのようなものがコンパイルとしてサポートされている場合よりもはるかにきれいではありません時間機能(私が理解したことから、さまざまなことを順番に試して失敗しない最初のテンプレートを指定する必要があります
...-supercat

...しかし、コンパイラーは潜在的な置換をコンパイルするためにかなりの労力を浪費する必要があり、それは最終的に破棄されます。「これが定数である場合、これを実行し、そうでない場合はこれを実行する」と「偽の開始」なしでより明確に言うことができると、よりクリーンなアプローチに思えます。
supercat

3

C ++は複数のプログラミング言語です。

a)「より良い」C b)オブジェクト指向言語c)それは、汎用プログラムを書くことを可能にする言語です

これらの機能はすべて個別に使用できますが、3つの機能を同時に使用すると最良の結果が得られます。それでも、そのうちの1つだけを選択すると、組み込みソフトウェアの品質が向上します。

a)「より良い」C

C ++は強力な型付き言語です。Cよりも強力です。プログラムはこの機能の恩恵を受けます。

一部の人々は、ポインターを恐れています。C ++には参照が含まれています。オーバーロードされた関数。

そして言うに値する:これらの機能はどれも、より大きなプログラムや遅いプログラムでは発生しませんでした。

b)オブジェクト指向言語です

誰かがこの投稿で、マイクロコントローラーで機械を抽象化するのは良い考えではないと言った。違う!組み込み技術者である私たち全員が、C ++のそれとは別のシンタックスで、常にマシンを抽象化してきました。この議論で私が見る問題は、一部のプログラマーがオブジェクトを考えることに慣れていないということです。そのため、OOPの利点が見えません。

マイクロコントローラーの周辺機器を使用する準備ができているときはいつでも、周辺機器はデバイスドライバーの形式で(ユーザー自身またはサードパーティから)抽象化されている可能性があります。前に言ったように、次の例が示すように、そのドライバーはC sintaxを使用します(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と例外に関するアドバイス:組み込みシステムではそれらを使用しないでください。絶対に避けてください!!


2

私の背景、埋め込み(mcu、pc、unix、その他)、リアルタイム。安全性が重要です。以前の雇用主をSTLに紹介しました。もうそれはしません。

Flameコンテンツ

C ++は組み込みシステムに適していますか?

うん C ++は書くのが面倒で、維持するのが面倒です。C +は大丈夫です(一部の機能を使用しないでください)

マイクロコントローラーのC ++?RTOS?トースター?組み込みPC?

繰り返しますが C +はそれほど悪くはありませんが、ADAはそれほど苦痛ではありません(それは本当に何かを言っている)。私のように幸運であれば、組み込みJavaを実行できます。チェックされた配列アクセスとポインター演算なしにより、非常に信頼できるコードが作成されます。組み込みJavaのガベージコレクターは最優先事項ではなく、スコープメモリとオブジェクトの再利用があるため、適切に設計されたコードはGCなしで永遠に実行できます。

OOPはマイクロコントローラーで役立ちますか?

確かです。UARTはオブジェクトです..... DMACはオブジェクトです...

オブジェクト状態マシンは非常に簡単です。

C ++はプログラマーをハードウェアから遠ざけすぎて効率的にしませんか?

PDP-11でない限り、CはCPUではありません。C ++はもともとCのプリプロセッサであったため、Bjarne StroustrupはAT&TでSimulaのシミュレーションが遅いことで笑われることを止めました。C ++はCPUではありません。

Javaバイトコードを実行するMCUを入手してください。Javaのプログラム。Cのみんなで笑います。

ArduinoのC ++(動的メモリ管理、テンプレート、例外なし)を「実際のC ++」と見なすべきですか?

いや。MCU用の世俗的なCコンパイラがすべてそうであるように。

第4に、Embedded JavaまたはEmbedded ADAは標準化されています(ish)。他のすべては悲しみです。


2
Javaをサポートするマイクロコントローラーを見つけるのは簡単ですか?これにより選択肢がかなり制限されると思います。また、パフォーマンスのペナルティについての経験は何ですか(uCでは通常JITがないため)。リアルタイムシステムでのGCの予測不能性の影響はどうですか?
fceconel

2
組み込みJavaをサポートするMCUは何ですか?
J.ポルファー

まずはwww.ajile.com。
ティムウィリスクロフト

Adaの場合は+1。Arduinosを含め、組み込みで大いに活用されています。
ブライアンドラモンド

Cで書かれたmicros用のポータブルJava VMはオープンソースです。dmitry.co/index.php?p=./04.Thoughts/...
ティムWilliscroft

-2

組み込みシステムは、複数のタスク用の汎用コンピューターではなく、特定のタスクを実行するように設計されています。組み込みシステムは、コンピューターのハードウェアとソフトウェアの組み合わせです。Cはすべての現代言語の母です。低レベルですがフルパワーの言語であり、あらゆる種類のハードウェアを扱います。したがって、C / C ++は組み込みシステム用のソフトウェアを開発するための最適な選択肢であり、すべての組み込みシステムで非常に使いやすくなっています。オペレーティングシステムUNIXはCで記述されています。ソフトウェア開発の成功は、特定のプロジェクトに最適な言語を選択することであるため、C / C ++言語が8ビットプロセッサと64ビットプロセッサの両方に適切であることが証明されていることは驚くべきことです; メモリがバイト、キロバイト、メガバイトのシステムで。Cにはプロセッサに依存しないという利点があり、これにより、プログラマは特定のプロセッサアーキテクチャの詳細ではなく、アルゴリズムとアプリケーションに集中できます。ただし、これらの利点の多くは、他の高レベル言語にも同様に適用されます。しかし、C / C ++は、他の多くの言語がほとんど失敗したところで成功しましたか?


6
これが議論に何を追加するのか本当に分かりません。
デイブツイード

-3

<暴言>

C ++はそもそもくだらない言語だと思います。OOPを使用する場合は、Javaプログラムを作成します。直接メモリアクセスは完全に(ab)useの範囲内であるため、C ++はOOPパラダイムを強制しません。

MCUを使用している場合は、おそらく100kB未満のフラッシュメモリについて話しています。メモリを抽象化した言語でプログラミングしたい場合:変数または配列を宣言すると、メモリ、ピリオドが取得されます。malloc(別名C ++の「新しい」キーワード)は、組み込みソフトウェアでの使用をほぼ禁止する必要があります。ただし、まれに、プログラムの起動中に1つの呼び出しが行われる場合があります。

地獄、組み込みプログラミングではCが十分に低レベルではない場合があり、変数をレジスタに割り当てたり、インラインアセンブリを記述して割り込みサービスルーチン(ISR)を強化したりする必要があります。「揮発性」などのキーワードは、理解することが非常に重要になります。オブジェクトレベルではなく、ビットレベルでメモリを操作することに多くの時間を費やしています。

なぜ物事は実際よりも単純だと思うようになりたいのですか?

</ rant>


ここでの私の問題は、単に、インターフェイスを処理するために完全に開発されたUSART1を制御するために書かれたドライバーの複雑さを知りたいのです。
Kortuk

1
私はあなたに反対票を投じませんでしたが、C ++はOOPを実施する必要はなく、それを行うためのツールを提供するだけであることを指摘したいと思います。優れたコーディング標準を実施することは、開発者の仕事です。言語がそれを簡単にすれば助けになりますが、言語はそれ自身では決してそれをしません。場合によっては、Cが読み取れないことがあります。
コルトゥク

1
すべての言語は何かに適しています。C ++は高速です。OOPがうまくいけば、複数の開発者が並行して作業し、未知のものをコーディングするのがはるかに簡単になります。これがゲーム開発に大きな牽引力を持っている理由だと思います。
トビージャフィー

1
はい私は同意する。組み込みの世界でそれを見る理由は、すでに配置されているさまざまなシステムと開発中の新しいシステムに大量の機能が追加されているためです。プロジェクトはどんどん大きくなります。それらを開発するのに時間がかかるか、CSの世界がすでにPCで行っていることを適用してゆがめます。
コルトゥク

5
C ++を適切に理解していない別の人。いつも何人いるのかと驚かされます。
Rocketmagnet
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.