• 締切済み

構造体の継承?再定義?

タイトルをどう書いてよいか分からなかったので あいまいなタイトルになってしまって申し訳ないです。 見て頂き有難う御座います。 どちらかと言えばCプログラミングのノウハウについて質問です。 ある構造体定義があります。 typedef struct _A{ int a; int b; }A; これを以下のように定義し直し、ユーザには Bの名前で公開させたいと考えています。 typedef A B; なぜかと言うと、Aはハード寄りの定義の為、 ハードの定義名を意識させない為にBの名前にした方が分かりやすいと 考えた為です。 このような実装により、分かりやすくなりますでしょうか? また、他に理想的な実装方法はありますでしょうか? よろしくお願い致します。

みんなの回答

回答No.2

No.1 です。 今後ハードウエアの変更が予想されるのであれば、typedef のような直接の割り当ては危険です。 それこそ、理想は、論理的な層での関数を準備して、その関数の定義以外の場所では、A の存在を見えなくすることです。 そうすれば、LEDの色数が増えても、それまでのプログラムは変更しなくてすみます。 たとえば、ハードウエアの機能が加わることで、物理的な割り当ての順序は簡単に変わってしまいますから。 オーバーヘッドの関係で関数をかぶせられない場合でも、型名をいじるのではなく、適切な変数名と、その後で、必要があれば、ポートの変換をしたほうがいいでしょう。 そうすれば、データ定義の段階で、(見えるにしても)どのポートにLEDが割あたっているのかわかります。 単純にLEDを制御するのなら、 struct port { unsigned b0: 1; unsigned b1: 1; unsigned b2: 2; }; に対して、 struct port LED_No1 = (ポートアドレスの割り当てなど) という定義で、 LED_No1.b0 = 0; で赤くなったり、 LED_No1.b1 = 1; で緑になったり とかですね。 さらにわかりやすくすのであれば、 #define RED b0 #defien GREEN b1 #define ON 0 #define OFF 1 で、 LED_No1.RED = ON; LED_No.1.GREEN = OFF; など。

yuichikun
質問者

お礼

なるほどとても参考になりました。 オーバーヘッドはそれ程制限が厳しいわけではないので 教えて頂いたイメージで関数をかぶせて実装してみたいと思います。 丁寧に説明して頂きありがとうございました。 質問の締め切りはもう少し時間をあけてから行いたいと思います。

回答No.1

ただ単に、ハードよりの名前を意識させないために、名前を変えるというのは、あまり意味がない気がします。 逆に懸念されるべき事が。 ハードよりの名前と、よりわかりやすい名前というのが考えられるということは、ハードウエアの要素(例えば、具体的なポート番号)と、ユーザーインターフェースの要素(例えば、LEDの色など)という考え方があるということだと思います。 そして、今は、たまたま、それらが、特定の構造体を通じて密接に関わっているということになります。 ケース1:今後ハードウエアの変更などが考えらる場合 このとき、ハードウエアの要素と、ユーザーインターフェースの要素の関係が壊れる可能性があります。この場合、構造体はどちらの要素に併せて変更すべきなのでしょうか? ハードウエアの構成に併せて変更したとして、LEDの色とアンマッチになるかも知れません。 しかも、プログラムの中では、別の名前の構造体を経由して、「正しい色」を制御しているとしたら、なぜ、目的の色が制御できないのか、判断に困るかも知れません。 ケース2:今後ハードウエアの変更などが「絶対に」ない場合 この場合、はじめから、Aを定義せずに、Bを使うというのも方法だと思います。 一般的にいえば、ユーザーから、ハードウエアを隠す場兄は、ユーザーインターフェースの層と、ハードウエアの層を分離することが考えられます。 ただ、少なからず、オーバーヘッドが発生するので、それとのかねあいになりますが。 例えば、ハードウエアのポートがあって、それに、LEDがつながっているとすれば、ユーザー側には、LED を制御するための関数だけを提供します。 具体的な、ハードウエアへのアクセスはその関数の中だけで行うわけです。 そうすれば、ハードウエアの変更があっても、プログラムの変更は最低限ですみます。 構造体などのデータに直接アクセスする場合でも、今回の例では、ハードウエア側には、構造体のAを、ユーザー側には、構造体Bを別々に定義します。(内容は同じになりますが) そして、プログラムからは、 1)構造体Bのデータにアクセスして、設定を行う 2)構造体Bをもとに、ハードウエアを制御するための関数を準備して、それを呼び出してもらう。今回の例では、構造体Bから構造体Aへの単純な代入になりますが。 のようにします。 ※設定値を読み出す必要があれば、逆の手順になります。 これは、ユーザー側の目的(LEDを点灯させるなど)と、ハードウエアの働き(特定のポートを ON/OFF するなど)を分離するということでもあります。 C++などで、「オブジェクト指向」をすると、このあたりが、もっとスマートに記述できるようになりますが。

yuichikun
質問者

補足

とても丁寧な回答ありがとうございました。 質問文の中で1点訂正なのですが、構造体Aの定義は 自担当コードではなく、includeしているハードウェア側の定義です。そして、例えばLEDだとした場合、今後色数が増える可能性があります。 やはりtypedefA B;が無難なやり方ですかね。

関連するQ&A