(組み込み用の特殊な用途なので、別のプログラムルーチンを使用せずに、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++は無しでお願いします。
宜しくお願いします。
少なくとも標準規格の範囲では、unionとstructの組み合わせだけで実現するのは不可能です。
特定の処理系の独自拡張機能を使えばできるかもしれませんが、そのような独自拡張はこれまで見たことがありません。
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が入ったデータにしたいのです。
>各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);\
}
詳しい説明ありがとうございます。
ですが、マクロを使う事も今回の場合やりたくなく、この方法も残念ながら出来ません。
ご回答ありがとうございます。
やはり無理なのですね。。。。。