int
ビットフィールドが符号付きか符号なしかは実装定義であることに注意してください。C ++標準はこれを示しており、C標準は異なる表現で同じ最終結果を達成します。
ISO / IEC 14882:2011 — C ++
§7.1.6.2単純型指定子
¶3...[注:char
タイプおよび特定のビットフィールド(9.6)のオブジェクトが符号付きまたは符号なしの量として表されるかどうかは、実装によって定義されます。指定子は、オブジェクトとビットフィールドに署名をsigned
強制します。char
他のコンテキストでは冗長です。—エンドノート]
§9.6ビットフィールド
¶3...ビットフィールドは整数型または列挙型(3.9.1)でなければなりません。プレーン(明示的に符号付きchar
でも符号なしでもない)、、、、、またはビットフィールドが符号付きか符号なしかは実装定義です。short
int
long
long long
ISO / IEC 9899:2011 — C
§6.7.2.1構造とユニオンの指定子
¶10ビットフィールドは、指定されたビット数で構成される符号付きまたは符号なし整数型を持っていると解釈されます。125)
125)上記6.7.2で指定されているように、使用される実際の型指定子がintまたはintとして定義されたtypedef-nameである場合、ビットフィールドが符号付きか符号なしかは実装定義です。
§6.7.2タイプ指定子
int
¶5...ビットフィールドの場合、指定子がと同じタイプを指定するか、同じタイプを指定するかは実装によって定義さsigned int
れunsigned int
ます。
§6.7.2のコンテキストは、などとint
組み合わせることができ、ルールが適用されることを示しています。C ++は、それをもう少し明確に指定します。もちろん、プレーンの符号は実装によって定義されています。short
long
char
符号なしビットフィールド
ビットフィールドのタイプが符号なしの場合、式はかなり単純です。
int d = (example.a << 7) | example.b;
署名されたビットフィールド
値が署名されている場合は、値example.a
が負でexample.b
正の場合、またはその逆の場合に値を決定するための主要な解釈演習があります。値が両方とも負または両方が正であっても、ある程度問題が発生します。
と仮定example.a = 7;
しexample.b = 12;
ます—の値は何である必要がありますd
か?おそらく同じ表現が当てはまりますが、1つ少ない場所でシフトする方がよいと主張することができます。
assert(example.a >= 0 && example.b >= 0);
int d = (example.a << 6) | example.b; // Alternative interpretation
他のケースはあなたが決めるために残されています。それはあなたが値に置きたい解釈に依存します。例えば:
int d = ((example.a & 0x0F) << 7) | (example.b & 0x7F);
これにより、符号付きの値が符号なしとして扱われるようになります。それはおそらくあなたが求めているものではありません。
修正された質問
example.a = 1001 // binary
example.b = 1010101 // binary
d = 10011010101 xxxxxxxxxxxxxxxxxxxxx
ここで、xは以前にdに属していた21ビットにすることができます。
これが機能するには、次のものが必要です。
d = (d & 0x001FFFFF) | ((((example.a & 0x0F) << 7) | (example.b & 0x7F)) << 21);
おそらく、使用する括弧の数を減らすことができます。そうするリスクがあるかどうかはわかりません。
連合
union
ただし、この改訂された仕様では、次のようなものを見たくなるかもしれません。
union u
{
struct
{
int a:4;
int b:7;
int c:21;
} y;
int x;
} example;
ただし、ビットフィールド内のビットのレイアウトはint x;
指定されておらず(最上位ビットが最初または最下位ビットが最初である可能性があります)、ユニオンの値にアクセスする場合は常に'についてつぶやきます。それはあなたに割り当てられた最後のものではありませんでした'未定義の動作を呼び出します。したがって、ビットフィールドのプラットフォームで定義された複数の側面を処理する必要があります。実際、この種の難問は、一般に、ビットフィールドが1つの特定のタイプのマシン(CPU)とコンパイラおよびオペレーティングシステムに密接に関連していることを意味します。彼らはあなたが求めている詳細のレベルでは非常に、非常に移植性がありません。