次のマルコが定義されているという質問があります。
TO_TI(a, b) ((b)<<13|(a))
次に、次のステートメントを呼び出します。
int c = TO_TI(1,2);
次に、結果を関数に渡しc
ます。この関数では、値 c に基づいて入力し、 の値を計算しますb
。
多くの場合、複数の整数を 1 つの大きな整数にパックするのは便利な方法であり、マクロを作成することはそれを正しく行うための良い方法です (ただし、インライン関数の方が好ましいかもしれません)。
重要なことは、自分が何をしているのかを知る必要があるということです! 基礎となるビット操作を正しく理解していない場合、または少なくともルールに従わない場合は、入力したものが返されません.
TO_TI マクロはa
、12 ビット以下の正の整数であれば問題なく動作します。b
データは 20 ビットを超えてはなりません (32 ビット ワードを想定)。
が署名されていない場合a
、次のように抽出できます。
unsigned int a = c & 0xFFF;
ただし、a
が署名されている場合は、次のように値を「符号拡張」する必要があります。
int a = ((int)c << 20) >> 20;
同様に、b
is 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 ビットのシステムには注意してください。
ルール:
これがビットフィールドが発明された理由であり、それらの使用を強く検討する必要があります。
質問を正しく理解していれば、次の結果のcが与えられます
c = b<<13 | a;
元の aとbを見つけることができますか?
による
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;