0

次のマルコが定義されているという質問があります。

TO_TI(a, b) ((b)<<13|(a))

次に、次のステートメントを呼び出します。

int c = TO_TI(1,2);

次に、結果を関数に渡しcます。この関数では、値 c に基づいて入力し、 の値を計算しますb

4

5 に答える 5

1

多くの場合、複数の整数を 1 つの大きな整数にパックするのは便利な方法であり、マクロを作成することはそれを正しく行うための良い方法です (ただし、インライン関数の方が好ましいかもしれません)。

重要なことは、自分が何をしているのかを知る必要があるということです! 基礎となるビット操作を正しく理解していない場合、または少なくともルールに従わない場合は、入力したものが返されません.

TO_TI マクロはa、12 ビット以下の正の整数であれば問題なく動作します。bデータは 20 ビットを超えてはなりません (32 ビット ワードを想定)。

が署名されていない場合a、次のように抽出できます。

unsigned int a = c & 0xFFF;

ただし、aが署名されている場合は、次のように値を「符号拡張」する必要があります。

int a = ((int)c << 20) >> 20;

同様に、bis signed の場合は符号拡張する必要がありますが、その方が簡単です:

int b = (int)c >> 12;

ただし、これは署名されていないため、署名拡張しないbように十分注意する必要があります。

unsigned int b = (unsigned int)c >> 12;

最後に、a負の値を許可する場合は、マクロを次のように定義する必要があります。

#define TO_TI(a, b) ((b)<<13|((a)&0xFFF))

(そうしないと、 の符号ビットがaを上書きしますb。)

3 つ以上の値が同じ整数にエンコードされている場合、事態はさらに複雑になります。intまた、 64 ビットのシステムには注意してください。

ルール:

  1. ビットに何をさせたいかを理解してください。
  2. ビット単位の演算子が符号付きおよび符号なしの値に対して行うことを理解します。
  3. 境界条件を慎重にテストします。

これがビットフィールドが発明された理由であり、それらの使用を強く検討する必要があります。

于 2013-05-30T13:01:39.927 に答える
0

質問を正しく理解していれば、次の結果のcが与えられます

c = b<<13 | a; 

元の abを見つけることができますか?

による

  • aの長さ (ビット数) : 上記の問題に加えて msb (最上位ビット) が 2^13 以上の場合、|操作はシフト ( )後のbの場所に影響を与えるため、ビット 13 のc値は、元のbまたは a からのものです。b << 13

  • bの長さ: 13 ビットのシフトはbに 2^13 (8192) を乗算することであり、 bが元々十分に大きい場合、シフト後にcがオーバーフローする可能性があります。つまり、結果はcサイズ (長さ)内に収まりません。以下のメソッドから取得されたbは、元のbよりも小さくなります。

したがって、a 8192 (2^13) より小さいが正の場合 (そうしないと、その msb がシフトされたbに到達します) 、左に 13 ビットシフトされた bがオーバーフローしませんcを使用して、 aおよびbを取得できます。

a = c & 8191; // 2^13 - 1 or 0x1fff in hexa
b = c >> 13;  
于 2013-05-30T12:43:54.920 に答える