Cでは、左側のオペランドが負の値の場合、ビット単位の左シフト演算によって未定義動作が呼び出されます。
ISO C99(6.5.7 / 4)からの関連する引用
E1 << E2の結果は、E1の左シフトE2ビット位置です。空になったビットはゼロで埋められます。E1に符号なしタイプがある場合、結果の値はE1×2 E2であり、結果タイプで表現可能な最大値より1を法として減少します。E1に符号付きタイプと非負の値があり、E1×2 E2が結果タイプで表現可能である場合、それが結果の値です。それ以外の場合、動作は定義されていません。
しかし、C ++では、動作は明確に定義されています。
ISO C ++-03(5.8 / 2)
E1 << E2の値は、E1(ビットパターンとして解釈される)の左シフトされたE2ビット位置です。空のビットはゼロで埋められます。E1がunsigned型の場合、結果の値はE1に数量2を掛けてE2の累乗になり、E1の型がunsignedlongの場合はULONG_MAX+1を法として、それ以外の場合はUINT_MAX+1になります。[注:定数ULONG_MAXおよびUINT_MAXはヘッダーで定義されています)。]
つまり、
int a = -1, b=2, c;
c= a << b ;
Cでは未定義動作を呼び出しますが、動作はC++で明確に定義されています。
ISO C ++委員会が、Cでの動作とは対照的に、その動作が明確に定義されていると見なすようになったのはなぜですか?
一方、implementation defined
左オペランドが負の場合の動作はビット単位の右シフト演算ですよね?
私の質問は、なぜ左シフト操作がCで未定義動作を呼び出すのか、そしてなぜ右シフト演算子が実装定義の動作だけを呼び出すのかということです。
PS:「標準がそう言っているので、それは未定義の振る舞いです」のような答えを与えないでください。:P