人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

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++は無しでお願いします。
宜しくお願いします。

●質問者: hiro007
●カテゴリ:コンピュータ 学習・教育
✍キーワード:BIT byte C++ C言語 けが
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● takagidotin
●27ポイント

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

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

◎質問者からの返答

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

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


2 ● kurukuru-neko
●27ポイント

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のデータ処理を無理に

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

◎質問者からの返答

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

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


3 ● kurukuru-neko
●26ポイント

>各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);\

}


◎質問者からの返答

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

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

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ