なぜそれが起こるのですか:
char p = 0;
p--;
System.out.println(p);
結果65535
コンパイル エラーや実行時例外が発生しないのはなぜですか? 文字が負になることはできないので、私はそれを期待していました。代わりに、逆さまからカウントを開始します。前もって感謝します。
コンパイル エラーや実行時例外が発生しないのはなぜですか?
言語仕様では、プリミティブ型の算術演算は modulo2^width
であることが義務付けられているため、-1
となり2^16-1
ますchar
。
整数演算のセクションでは、次のように述べられています。
組み込みの整数演算子は、オーバーフローまたはアンダーフローを決して示しません。
そのため、例外のスローが禁止されます。
使用される後置デクリメント演算子については、具体的には、その動作は15.14.3で指定されています
それ以外の場合は、値 1 が変数の値から減算され、差が変数に格納されます。減算の前に、値 1 と変数の値に対してバイナリ数値昇格 (§5.6.2) が実行されます。必要に応じて、プリミティブ変換 (§5.1.3) を縮小することによって差異を縮小するか、格納する前に変数の型へのボックス化変換 (§5.1.7) を適用します。後置デクリメント式の値は、新しい値が格納される前の変数の値です。
バイナリ数値昇格は、値と 1 の両方をint
(ここでの型は であるchar
ため) に変換するため、中間結果-1
は として得られint
、縮小プリミティブ変換が実行されます。
符号付き整数から整数型 T への縮小変換では、下位 n ビットを除くすべてのビットが単純に破棄されます。ここで、n は型 T を表すために使用されるビット数です。数値の大きさに関する情報が失われる可能性に加えて、 、これにより、結果の値の符号が入力値の符号と異なる場合があります。
結果のchar
値は(Java は符号付き整数型の 2 の補数表現を指定しているため、単項マイナス0xFFFF
の仕様で明示的に述べられているため):
整数値の場合、否定はゼロからの減算と同じです。Java プログラミング言語は整数に 2 の補数表現を使用し、2 の補数の値の範囲は対称的ではないため、最大の負の int または long を否定すると、同じ最大の負の数になります。この場合、オーバーフローが発生しますが、例外はスローされません。すべての整数値 x について、-x は (~x)+1 に等しくなります。
範囲外の結果に対する一般的なラップアラウンド動作については、乗算演算子の指定の例として:
整数の乗算がオーバーフローした場合、結果は十分に大きな 2 の補数形式で表される数学的積の下位ビットになります。その結果、オーバーフローが発生した場合、結果の符号は、2 つのオペランド値の数学的積の符号と同じではない可能性があります。
同様のフレーズが整数加算の仕様で発生し、 を満たすa - b == a + (-b)
には減算が必要になるため、オーバーフローの動作が続きます。
それがJava言語の定義方法だからです。ランタイムは各操作で境界をチェックしません (おそらく非常にコストがかかるため)。オーバーフローまたはアンダーフローするだけです。