C言語でunionとstructを組み合わせて、飛び飛びのビート割り当てとなる様な設定をしたいです。

(組み込み用の特殊な用途なので、別のプログラムルーチンを使用せずに、unionとstructの組み合わせのみで行いたいです。)

具体的にはUnionAとしてByteBとByteCを共用体に設定したとして、
UnionA.ByteB=0x03; (つまり1bit目と"2"ビット目を1)
とした場合に、UnionA.ByteCの値が0x05 (つまり1bit目と"3"ビット目が1)となる様なbitの割り付けがしたいです。bit溢れ等は別途方法を考えます。
UnionAとして1bit単位のビットフィールドを設定して、それぞれ1bitづつ書き込めばそういう処理ができるのは分かっているのですが、今回はあくまでbyte単位で書き込んでbyte単位で読み出せる方法を考えています。
C言語限定で、C++は無しでお願いします。
宜しくお願いします。

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2007/02/24 18:11:18
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:takagidotin No.1

回答回数37ベストアンサー獲得回数0

ポイント27pt

少なくとも標準規格の範囲では、unionとstructの組み合わせだけで実現するのは不可能です。

特定の処理系の独自拡張機能を使えばできるかもしれませんが、そのような独自拡張はこれまで見たことがありません。

id:hiro007

ご回答ありがとうございます。

やはり無理なのですね。。。。。

2007/02/22 14:00:24
id:kurukuru-neko No.2

回答回数1844ベストアンサー獲得回数155

ポイント27pt

C言語の標準ではそのような事は実現不可能。

バイト境界の意味でbyte書き込みをする場合、

データは必ず境界あわせされるので不可能。

操作データが2進数で

0x03 = 11

0x05 = 101

なので2bitだと存在もとのデータに存在しないデータが1bit

増える割当は、処理系依存でしか実現できません。

かりにビットフィールドアクセスをするにしても

どのような単位で実際にハードウェアアクセスされて

いるかはわかったものではありません。

組込み系であればなおさら問題

(かりに出来てもそのような実装は保守できない)

bit割当だけみて相互変換できるパータンは

1/10 < -- > 10 1

01/1 < -- > 1 01

/にbyte境界がある必要があると推定出来る。

Little Endianの場合

10xxxxxx xxxxxxx1

1xxxxxxx xxxxxx01

Big Endianの場合

xxxxxx01 1xxxxxxx

xxxxxxx1 10xxxxxx

が考えられるが考えられる実装としてはコンパイル

オプションで構造体のエンディアンを切替え出来る

仕様があれば出来る可能性はある。

エンディアンの違うCPUのデータ処理を無理に

やろうとしていませんか?

id:hiro007

やりたいのはN bitのカウンタintNを上位 or 下位からI/O portに1 bitづつ出力したいのですが、その時に各bitの間に0をデリミタの様に入れ込みたいのです。

もちろんシフト等を活用すればできますし、そもそもI/O出力の部分でも間に0を入れれば出来るのですが、訳あって、そこを触らずにunion/structを使う事で変数の時点で既に0が入ったデータにしたいのです。

2007/02/22 13:58:55
id:kurukuru-neko No.3

回答回数1844ベストアンサー獲得回数155

ポイント26pt

>各bitの間に0をデリミタの様に入れ込みたいのです。

コンパイラーはビットフィールドを使う限り境界あわせ

は必ず発生するのでビットフィールドで実現する事に

なります。 データはそのデータ型に応じたデータ

を取り出しマスクするだけなのでそのデータ構造

そのものがメモリー上と変化して欲しい状況の実現は

不可能です。

従って期待するような動作は実現不可能

普通に考えればI/O部分で処理すべきと考えます。

どうしても代入時に処理したいなら、代入操作を

マクロ、関数等でカバーする以外方法はない。

SetIOBits(UnionA.ByteB,0x03);

UnionA.ByteB = SetIOBits(0x03);

例えば2bit で 1bit目の後に0を入れるだけなら

マクロでも簡単に実現できる。

======何処かで定義========

ノーチエックです

unsigned char SetIOBits_map[4] = {

0x00,0x01,0x04,0x05

};

extern unsigned char SetIOBits_map[4];

#define SetIOBits(_setvar,_val) { \

_setvar = SetIOBits_map[ _val & 0x03 ];\

}

or

#define SetIOBits(_val) SetIOBits_map[ _val & 0x03 ]

or

#define SetIOBits(_setvar,_val) { \

unsigned char _tmp = _val & 0x03;\

_setvar = _tmp + (_tmp & 0x02);\

}


id:hiro007

詳しい説明ありがとうございます。

ですが、マクロを使う事も今回の場合やりたくなく、この方法も残念ながら出来ません。

2007/02/24 18:10:19

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません