20

さまざまな組み込みシステムの開発に携わってきました。それらはすべて、 などの型にtypedefs (または#defines) を使用していUINT32ます。

これは、型のサイズをプログラマーに認識させ、オーバーフローなどの可能性をより意識させるため、優れた手法です。

しかし、一部のシステムでは、コンパイラとプロセッサがプロジェクトの存続期間中変更されないことがわかっています。

では、プロジェクト固有の型を作成して適用するという決定に影響を与えるものは何でしょうか?

編集私は自分の質問の要点をなんとか失ったと思います。おそらくそれは本当に2つです。

組み込みプログラミングでは、インターフェイスに特定のサイズの型が必要になる場合があり、RAM などの限られたリソースに対処するためにも必要になる場合があります。これは避けられませんが、コンパイラからの基本的な型を使用することを選択できます。

それ以外の場合、型の重要性は低くなります。
オーバーフローが発生しないように注意する必要があり、レジスタとスタックの使用に注意する必要がある場合があります。につながる可能性がありUINT16ますUCHARUCHARただし、コンパイラの「綿毛」を追加できるなどのタイプを使用します。レジスターは一般的に大きいため、一部のコンパイラーはコードを追加して、結果を強制的に型に入れる場合があります。

i++;
になることができる
REG,1 を追加
AND REG、0xFF
これは不要です。

だから、私の質問は次のようになるべきだったと思います:-

組み込みソフトウェアの制約を考えると、多くの人がそれに取り組むプロジェクトに設定する最善のポリシーは何ですか - すべての人が同じレベルの経験を持つわけではありません.

4

9 に答える 9

17

私は型の抽象化をめったに使用しません。主観性の昇順でソートされた私の議論は次のとおりです。

  1. ローカル変数は、レジスターに収まるようにするという意味で、構造体のメンバーや配列とは異なります。32b/64b ターゲットではint16_t、コンパイラは のセマンティクスに従って /force/overflow に操作を追加する必要があるため、local は local int に比べてコードを遅くする可能性がありint16_tます。C99 はintfast_ttypedef を定義していますが、私の知る限り、プレーンな int も同様にレジスタに収まり、短い名前であることは確かです。

  2. これらの typedef を好む組織はINT32, int32_t, INT32_T、ほと​​んどの場合、いくつかの typedef を使用することになります (無限に続く)。したがって、組み込みタイプを使用する組織は、ある意味で、名前のセットを 1 つだけ持つほうがよいと言えます。stdint.h、windows.h、または既存のものの typedef を使用してほしいと思います。ターゲットにその .h ファイルがない場合、追加するのはどれほど難しいでしょうか?

  3. typedef は理論的には移植性を高めることができますが、私は、それらから何も得られませんでした。32b ターゲットから 16b ターゲットに移植できる便利なシステムはありますか? 32b ターゲットに移植するのが簡単ではない 16b システムはありますか? さらに、ほとんどの var が int の場合、実際には新しいターゲットの 32 ビットから何かを得ることができます。int16_t、あなたはしません。また、移植が難しい場所は、いずれにせよ手作業による検査が必要になる傾向があります。ポートを試す前は、それらがどこにあるのかわかりません。ここで、いたるところに typedef があれば移植がとても簡単だと誰かが考えている場合、移植の時が来たら、ほとんどのシステムでは起こりませんが、コード ベース内のすべての名前を変換するスクリプトを作成してください。これは、「手作業による検査は不要」のロジックに従って機能するはずであり、実際にメリットが得られる時点まで作業を延期します。

  4. 移植性が typedef の理論上の利点である場合、可読性は確実に失われます。stdint.h: を見てください{int,uint}{max,fast,least}{8,16,32,64}_t。たくさんの種類。プログラムには多くの変数があります。int_fast16_tどれが必要でどれが必要かを理解するのは本当に簡単uint_least32_tですか? それらの間で何回静かに変換し、それらを完全に無意味にしていますか? (私は特に BOOL/Bool/eBool/boolean/bool/int 変換が好きです。typedef を義務付ける整然とした組織によって書かれたすべてのプログラムには、それが散らばっています)。

  5. もちろん、C++ では、オーバーロードされた演算子などでテンプレート クラスのインスタンス化の数値をラップすることで、型システムをより厳密にすることができます。これは、「class Number<int,Least,32> has no operator+ overload for argument of type class Number<unsigned long long,Fast,64>、候補は...」という形式のエラー メッセージが表示されることを意味します。これも「可読性」とは呼ばないでください。これらのラッパー クラスを正しく実装できる可能性は微視的であり、ほとんどの場合、無数のテンプレートのインスタンス化がコンパイルされるのを待ちます。

于 2008-08-17T19:15:31.027 に答える
7

C99 標準には、標準サイズの整数型が多数あります。C99 をサポートするコンパイラを使用できる場合 (gcc はサポートします)、これらを見つける<stdint.h>ことができ、プロジェクトで使用することができます。

また、組み込みプロジェクトでは、単位変換などの一種の「セーフティ ネット」として型を使用することが特に重要になる場合があります。C++ を使用できる場合は、基になるスカラー型の操作としてコンパイルされる C++ 型システムによって (テンプレートを介して) 定義された物理ユニットで作業できる「ユニット」ライブラリがいくつかあることを理解しています。たとえば、これらのライブラリでは、ユニットが整列していないため、 adistance_tに aを追加できません。mass_t実際にはコンパイラ エラーが発生します。

C++ や、そのようにコードを記述できる他の言語で作業できない場合でも、少なくとも C 型システムを使用して、そのようなエラーを目で確認するのに役立てることができます。meter_t(実際には、これが Simonyi のハンガリー語表記の本来の意図でした。) aに aを追加してもコンパイラが怒鳴らないからといって、gram_tそのような型を使用してはならないというわけではありません。その場合、コード レビューはユニット エラーの発見においてはるかに生産的になります。

于 2008-08-10T09:03:24.057 に答える
4

私の意見では、最小/最大/特定のサイズに依存している場合は、(たとえば)が32バイトであると想定するのではなく、代わりに使用てください(コンパイラがC99をサポートしていると想定)。unsigned intuint32_t

于 2008-08-11T04:29:28.650 に答える
4

特にシステム API を定義するために stdint.h 型を使用するのが好きです。これは、項目の大きさが明示的に示されているためです。Palm OS の昔、システム API は、非常に古典的な Mac OS から継承された "Word" や "SWord" などの希望に満ちた型を使用して定義されていました。彼らは代わりに Int16 と言うようにクリーンアップを行い、特にそのシステムの奇妙な 16 ビット ポインターの問題で、初心者が API を理解しやすくしました。彼らが Palm OS Cobalt を設計していたとき、stdint.h の名前と一致するようにそれらの名前を再度変更し、さらに明確にして、管理しなければならない typedef の量を減らしました。

于 2008-08-20T14:12:16.360 に答える
3

MISRA 標準では、typedef の使用が推奨 (要求) されていると思います。

個人的な観点から言えば、typedef を使用すると、特定の型のサイズ (ビット/バイト単位) について混乱することはありません。私は、主任開発者が int などの標準型と UINT32 などのカスタム型を使用して、両方の開発方法を試みているのを見てきました。

コードが移植可能でない場合、typedef を使用するメリットはほとんどありませ、私のように、両方のタイプのソフトウェア (移植可能な環境と固定された環境) で作業している場合は、標準を維持し、カスタマイズされた型を使用すると便利です。少なくともあなたが言うように、プログラマーは自分がどれだけのメモリを使用しているかをよく知っています。考慮すべきもう 1 つの要因は、コードが別の環境に移植されないという確信があるかどうかです。ハードウェア エンジニアが突然ボードを変更しなければならなかったため、プロセッサ固有のコードを変換する必要があるのを見たことがあります。

于 2008-08-24T14:48:54.007 に答える
1

一貫性、利便性、読みやすさ。「UINT32」は、一部のシステムで同等の「unsigned long long」よりもはるかに読み取り可能で書き込み可能です。

また、コンパイラとプロセッサはプロジェクトの存続期間中固定される場合がありますが、そのプロジェクトのコードは別のプロジェクトで新しい命を見つける可能性があります。この場合、一貫したデータ型を持つことは非常に便利です。

于 2008-08-10T08:11:40.730 に答える
1

組み込みシステムがなんらかの理由でセーフティ クリティカル システム(または類似のシステム) である場合は、(必要でない場合でも) プレーンな型よりも typedef を使用することを強くお勧めします。

TKとして。前に言ったように、MISRA-Cにはそうするための (推奨) ルールがあります。

ルール 6.3 (推奨): サイズと符号を示す typedef は、基本的な数値型の代わりに使用する必要があります。

(MISRA-C 2004 より; MISRA-C 1998 の Rule #13 (adv) です)


この領域の C++ にも同じことが当てはまります。例えば。JSF C++ コーディング標準:

AV ルール 209 UniversalTypes ファイルは、開発者が使用するすべての標準タイプを定義するために作成されます。[uint16、int16、uint32_t など]

于 2015-06-10T16:43:56.180 に答える
1

を使用<stdint.h>すると、PC での単体テスト用にコードの移植性が向上します。

すべてのテストを行うとかなり苦戦する可能性がありますが、ターゲット システムでは依然として壊れますint

于 2016-06-20T10:07:49.380 に答える
0

私は変かもしれませんが、整数型には ub、ui、ul、sb、si、および sl を使用しています。おそらく、16 ビットの「i」は少し古いように見えますが、uw/sw よりも ui/si の外観が好きです。

于 2010-08-14T03:23:24.137 に答える