C# のシフト演算子を扱っているときに、左シフト演算子の予期しない動作に遭遇しました。
次に、この単純な関数を試しました:
for (int i = 5; i >= -10; i--) {
int s = 0x10 << i;
Debug.WriteLine(i.ToString().PadLeft(3) + " " + s.ToString("x8"));
}
この結果:
5 00000200
4 00000100
3 00000080
2 00000040
1 00000020
0 00000010
-1 00000000 -> 00000008 expected
-2 00000000 -> 00000004 expected
-3 00000000 -> 00000002 expected
-4 00000000 -> 00000001 expected
-5 80000000
-6 40000000
-7 20000000
-8 10000000
-9 08000000
-10 04000000
今日まで、<<
演算子は第 2 オペランドの負の値を処理できると思っていました。
MSDNは、2 番目のオペランドに負の値を使用した場合の動作について何も伝えていません。しかし、MSDN によると、演算子は下位 5 ビット (0 ~ 31) のみを使用し、負の値に適合するはずです。
long
私もvalues:で試しましlong s = 0x10L << i;
たが、同じ結果になりました。
それで、ここで何が起こりますか?
編集
回答で述べたように、負の値の表現はこれの理由ではありません。
すべてのケースで同じ間違った結果が得られました。
0x10<<-3 = 0x00000000 (wrong!)
0x10<<(int)(0xfffffffd) = 0x00000000 (wrong!)
0x10<<(0x0000001d = 0x00000000 (wrong!)
expected = 0x00000002
編集 #2
これら 2 つのうちの 1 つが true である必要があります。
1) シフト演算子は実際のシフト演算子であるため、結果は次のようになります:
1a) 0x10 << -3 = 00000002
1b)0x10 << -6 = 00000000
2) シフト演算子は回転演算子なので、結果は次のようになります:
2a) 0x10 << -3 = 00000002
(1a) と同じ
2b)0x10 << -6 = 40000000
しかし、表示された結果は 1) にも 2) にも当てはまりません!!!