Linux カーネル コードにいくつかの変更を加えて再コンパイルするという任務が与えられました。このコード行が何をするのか理解するのに苦労しています:
p->time_slice = (current->time_slice + 1) >> 1;
もっと正確に言うと、なぜ末尾に ">> 1" があるのですか?
Linux カーネル コードにいくつかの変更を加えて再コンパイルするという任務が与えられました。このコード行が何をするのか理解するのに苦労しています:
p->time_slice = (current->time_slice + 1) >> 1;
もっと正確に言うと、なぜ末尾に ">> 1" があるのですか?
">>" は、値をビットごとに右にシフトすることを意味します。「x >> y」は、2^y で除算して結果を切り捨てることと同じです。結果を切り捨てることは、ほとんどすべての場合に切り捨てを意味しますが、負の数の場合は別の実装が存在する可能性があります。これがあなたに起こっていると思われる場合は、コメントを参照してください。
それはビットごとのシフト演算子です。値をビットの配列として扱い、すべてを 1 ビット右に (最下位ビットに向かって) シフトします。これは、正の数を切り捨てて 2 で除算することと同じです。シフトは、2 の累乗で割る簡単な方法として使用されます。1 ( >> 1
) シフトすると 2 で割ることになり、2 ( >> 2
) シフトすると 4 で割ることになります。
たとえば、4 ビット整数を使用している場合に、これがどのように機能するかの例をいくつか示します。
6 >> 1
0110 -> 0011
3
7 >> 1
0111 -> 0011
3
6 >> 2
0110 -> 0001
1
負の数の場合は、もう少し複雑です。C 標準では、負の数の形式は指定されていません。最近のほとんどのマシンでは、それらは2 の補数で格納されます。つまり、負の数を表すには、正の表現を使用し、すべてのビットを反転して 1 を追加します。次に、最上位ビットを使用して符号ビットを示します。負の数を右シフトする場合、2 つの解釈が可能です。1 つは常に 0 を最上位ビットにシフトするもので、もう 1 つは一致する値を既存のものにシフトインするもので、「符号拡張」として知られています。
-2 >> 1
1110 -> 0111
7
1110 -> 1111
-1
C 標準では、これらの解釈のどれを実装で使用する必要があるかは指定されていません。GCC は、正の場合と同様に、2 で除算して切り捨てと同等の、より期待される符号拡張を行います。切り捨てとは、ご想像のとおり、「ゼロに向かって」ではなく、「負の無限大に向かって」という意味であることに注意してください。
-3 >> 1
1101 -> 1110
-2