掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.29145

スマートな記述(struct/union)
投稿者---RiSK(2006/12/05 14:58:51)


こんにちは。RiSKです。
端的な題名がつけられませんでした。

先頭要素が共通の構造体へのポインタを複数持つ共用体から
その構造体の共通部分へアクセスする際に,
スマートな記述ができないかと思い質問します。

以下のコードをご覧ください。
#include<stdio.h>
struct StructA{
    int a1;
    int a2;
};
struct StructB{
    struct StructA sa;
    int b;
};
union UnionA{
    struct StructA*psa;
    struct StructB*psb;
}ua;
int main(void){
    struct StructA sa={314,159};
    ua.psa=&sa;
    printf("%d, %d\n",ua.psa->a1,ua.psa->a2);       // (1)
    printf("%d, %d\n",ua.psb->sa.a1,ua.psb->sa.a2); // (2)
//  printf("%d, %d\n",ua->a1,ua->a2);               // (3)
}

(1)と(2)は当然ながら同じ要素(a1とa2)を表示していますが,
(3)のような記述ができたらスマートだなぁと思うわけです。

無名の構造体や共用体を使っても構わないので,
何か妙案は無いでしょうか?

(3)でなくとも,短かったり,分かりやすかったりする
別の方法でも構いません。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:スマートな記述(struct/union) 29146 keichan 2006/12/05 16:14:08
<子記事> Re:スマートな記述(struct/union) 29148 たかぎ 2006/12/05 16:34:20
<子記事> Re:スマートな記述(struct/union) 29184 RiSK 2006/12/07 23:02:39


No.29146

Re:スマートな記述(struct/union)
投稿者---keichan(2006/12/05 16:14:08)


unionメンバが持っているポインタ変数を無視しているかのように見せるですか。
C言語としてそのまま完全に解決する。というのは難しそうですね^^;
C++であればoperator->のオーバーロードとマクロでなんとか出来そうですが。。。

可読性の面で、ということであればこんなのどうでしょう?

#define <stdio.h>

#define MEMBER_A(x)  (x##.psa)
#define MEMBER_B(x)  (x##.psb)

struct StructA
{
    int a1;
    int a2;
};

struct StructB
{
    struct StructA sa;
    int b;
};

union UnionA
{
    struct StructA* psa;
    struct StructB* psb;
}ua;

int main()
{
    struct StructA sa = {314, 159};
    ua.psa = &sa;
    printf("%d, %d", MEMBER_A(ua)->a1, MEMBER_A(ua)->a2);
    return 0;
}



#改良すればもっと使えるようになるかも?


この投稿にコメントする

削除パスワード

No.29147

Re:スマートな記述(struct/union)
投稿者---keichan(2006/12/05 16:16:05)


typo..

#define <stdio.h>

#include <stdio.h>


この投稿にコメントする

削除パスワード

No.29148

Re:スマートな記述(struct/union)
投稿者---たかぎ(2006/12/05 16:34:20)
http://takagi.in/


要するに、C++の派生クラスのようなことをCでやりたいということですね。
# 外していたら済みません。

#include<stdio.h>
struct StructA{
    int a1;
    int a2;
};
struct StructB{
    struct StructA sa;
    int b;
};
struct StructA *psa;
int main(void){
    struct StructB sb={314,159,123};
    psa=&sb.sa;
    printf("%d, %d\n",psa->a1,psa->a2);
}
というのが一番素直なやり方だと思います。
共用体を使うと、派生クラス?が増えるたびに編集しないといけなくなりますから。



この投稿にコメントする

削除パスワード

No.29149

Re:スマートな記述(struct/union)
投稿者---たかぎ(2006/12/05 16:45:03)
http://takagi.in/


ちなみに、ダウンキャストはこんな感じで。
#define down_cast(type, member, ptr)  ((type*)((char*)(ptr)-offsetof(type, member)))
printf("%d\n",down_cast(struct StructB, sa, psa)->b);
このやり方なら、多重継承でもわけ無しです。



この投稿にコメントする

削除パスワード

No.29184

Re:スマートな記述(struct/union)
投稿者---RiSK(2006/12/07 23:02:39)


みなさん,レスありがとうございました。

>(1)と(2)は当然ながら同じ要素(a1とa2)を表示していますが,
>(3)のような記述ができたらスマートだなぁと思うわけです。

こんな変な美的センスに付き合ってくださってありがとうございます。


まず,マクロを用いる方法です。
自分一人のコードでしたら,おもしろいので
ありだったかもしれません。

しかし,今回のケースは(書いてるのは一人なのですが)
不特定多数の目に触れることを前提にコードを書いているので,
却下とします。
・マクロを書く/書き換えるのがめんどくさい。
・マクロを覚えるのがめんどくさい。
・マクロを使うのがめんどくさい。
ってのが,大きいです。
本気でマクロを使うとしたら,プレフィックスをつける
可能性が高いので,それだと,タイプ数までも
ふくれあがる事になってしまいます。


続いて,ポインタ経由の「一番素直なやり方」です。
確かにコードはすっきりしていて,私も素直だと思います。
とりあえず,これを候補として実際に使ってみたいと思います。
無駄な宣言が気にくわないのですけど。


>要するに、C++の派生クラスのようなことをCでやりたいということですね。

ご名答。
C#とかC++のまねっこをCでやろうという,あほな企画やってます。

>共用体を使うと、派生クラス?が増えるたびに編集しないといけなくなりますから。

それはたぶん大丈夫です。
ベースクラス側ではなく,
継承したクラスの方でunionのメンバを増やしていますので。

継承したい場合,ベースクラス側のunionの記述をコピーして,
自分自身へのポインタを追加すればOKなように,今のところ考えてます。


もしかしたら,結局自分が考えていたような記述になる可能性がありますが,
みなさんが,いくつかの提案をしてくださったことに感謝します。
ありがとうございました。

# たかぎさんには油を売っていたことがばれているでしょうから,
# その点もお詫びします。


この投稿にコメントする

削除パスワード

No.29185

Re:スマートな記述(struct/union)
投稿者---RiSK(2006/12/07 23:24:10)


おまけ。

>>要するに、C++の派生クラスのようなことをCでやりたいということですね。
>
>ご名答。
>C#とかC++のまねっこをCでやろうという,あほな企画やってます。

今回の質問は,いっぱい継承した際に

virtualTable->base.base.base.base.base.base.base->ToString(this);

みたいなことが嫌だったってのが,その背景にあります。
とりあえず,共用体を使えば

virtualTable->Object->ToString(this);

となってくれるのではないかと,淡い期待を持ちつつ
今回は終了といたします。


この投稿にコメントする

削除パスワード

No.29187

Re:スマートな記述(struct/union)
投稿者---たかぎ(2006/12/07 23:45:25)
http://takagi.in/


>今回の質問は,いっぱい継承した際に
>
>virtualTable->base.base.base.base.base.base.base->ToString(this);
>
>みたいなことが嫌だったってのが,その背景にあります。

なるほど。

単純継承だけでよいのであれば、キャストすれば済む気もします。
構造体のアドレスと、その構造体の先頭メンバのアドレスが一致することは保証されているわけですから。

多重継承(インタフェース継承を含む)になると、ちょっと厳しいですね。


この投稿にコメントする

削除パスワード

No.29189

Re:スマートな記述(struct/union)
投稿者---RiSK(2006/12/08 01:01:57)


>単純継承だけでよいのであれば、キャストすれば済む気もします。
>構造体のアドレスと、その構造体の先頭メンバのアドレスが一致することは保証されているわけですから。

そうですね。
ただ,キャストはコードをいじくりまわしたときにも,
コンパイラを黙らせてしまうので,極力使いたくないんですよね。
# 実際,使ってますけど...


>多重継承(インタフェース継承を含む)になると、ちょっと厳しいですね。

そうですね。これに関しては,(妄想段階ですが)
仮想テーブルのoffsetを求める必要があるので,

IEnumerable GetIEnumerable(Object this);

あるいはマクロを用意して

IEnumerable static_cast(IEnumerable)(Object this);

みたいなのが必須になりそうです。


この投稿にコメントする

削除パスワード

No.29186

Re:スマートな記述(struct/union)
投稿者---たかぎ(2006/12/07 23:36:34)
http://takagi.in/


>C#とかC++のまねっこをCでやろうという,あほな企画やってます。

CotNetですよね。そういう企画は結構好きです。
直接実用にはならないかも知れませんが、副産物として、いろんなTipsが生まれたりしますから。
まるで、錬金術の研究過程で化学が進歩したり、永久機関の研究過程で熱力学の法則が発見されたかのように...

私も時間ができたら、STLをCでまねっこしたSML(Standard Macro Library)でも作ろうかな。



この投稿にコメントする

削除パスワード

No.29188

Re:スマートな記述(struct/union)
投稿者---RiSK(2006/12/08 00:53:50)


# チラシの裏

>>C#とかC++のまねっこをCでやろうという,あほな企画やってます。
>
>CotNetですよね。そういう企画は結構好きです。

うぉおおおおおおおっって,そーゆーキーワード書くなぁあああああ。
かなりネタなんですから。

>直接実用にはならないかも知れませんが、副産物として、いろんなTipsが生まれたりしますから。

いや,実用にしますよ。私が実用する予定ですから。

>私も時間ができたら、STLをCでまねっこしたSML(Standard Macro Library)でも作ろうかな。

イテレータとかIEnumerableを再現すれば,
かなーり楽しい感じになる予感はしてます。

とりあえず,今は継承と多態を美しく書けるような設計をしようかな。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧