0

私は次の構造を持っています:

struct
{
   int a:4;
   int b:7;
   int c:21;
} example;

a と b を組み合わせて、C++ で整数 d を形成したいと思います。たとえば、整数 d を形成するために、a のビット値を b のビット値の左側に配置したいと考えています。これはC ++でどのように実装されていますか?

例:

= 1001

b = 1010101

int d = 10011010101 xxxxxxxxxxxxxxxxxxxxx をお願いします

ここで、x は、以前に d に属していた 21 ビットにすることができます。構造体「例」では、a が最初の 4 ビットを占め、b が次の 7 ビットを占めるため、a と b の値をそれぞれビット位置 0 ~ 3 と 4 ~ 10 に入れたいと思います。

私が混乱しているのは、変数 a と変数 b の両方が最上位ビットに「符号」ビットを持っていることです。これは結果に影響しますか?変数 a と変数 b のすべてのビットが、整数 d の最終結果に使用されていますか? 整数 d は、変数 a のビットと変数 b のビットを連結したように見えますか?

ありがとう

4

1 に答える 1

2

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でも符号なしでもない)、、、、、またはビットフィールドが符号付きか符号なしかは実装定義です。shortintlonglong 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 intunsigned intます。

§6.7.2のコンテキストは、などとint組み合わせることができ、ルールが適用されることを示しています。C ++は、それをもう少し明確に指定します。もちろん、プレーンの符号は実装によって定義されています。shortlongchar


符号なしビットフィールド

ビットフィールドのタイプが符号なしの場合、式はかなり単純です。

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)とコンパイラおよびオペレーティングシステムに密接に関連していることを意味します。彼らはあなたが求めている詳細のレベルでは非常に、非常に移植性がありません。

于 2012-11-21T02:17:55.463 に答える