Byte がオーバーフローすると実際に何が起こるのでしょうか?
質問
Byte がオーバーフローすると実際に何が起こるのでしょうか?
あると言ってください
byte byte1 = 150; // 10010110
byte byte2 = 199; // 11000111
ここでこの追加を行うと
byte byte3 = byte1 + byte2;
最終的には byte3 = 94 になると思いますが、実際はどうなりますか?何らかの方法で他のメモリを上書きしたのでしょうか、それともこれはまったく無害なのでしょうか?
解決
とても簡単です。追加を行い、8ビット以上の数で外れます。 9番目のビット(1つである)は、「Falls Off」だけで、残りの8ビットが94を形成します。
(はい、それは無害です)
他のヒント
あなたが持っている場合はC#で
checked { byte byte3 = byte1 + byte2; }
オーバーフローの例外がスローされます。コードがコンパイルされています unchecked
デフォルトで。他の答えが言っているように、値は「包み込み」になります。つまり、 byte3 = (byte1 + byte2) & 0xFF;
上部ビットは切り捨てられます。それは他の記憶に有害ではなく、意図しない結果の点でのみ有害です。
キャリーフラグが設定されます...しかし、結果があなたが期待するものではないことに加えて、悪影響はないはずです。
通常(および正確な動作は言語とプラットフォームに依存します)、結果はModulo-256を取得します。 IE 150+199 =349。349mod 256 = 93。
これは他のストレージに影響しないはずです。
質問C#、C ++、およびCにタグを付けたので、CとC ++について答えます。署名型タイプのC ++オーバーフローで sbyte
(これは、そうだと思います signed char
C/C ++で)は、未定義の動作をもたらします。ただし、署名されていないタイプの場合 byte
(これは unsigned char
c ++で)結果はmodulo2を取りますn ここで、nは署名されていないタイプのビット数です。 C#では、2番目のルールが保持され、署名されたタイプがそれらがある場合、例外を生成します checked
ブロック。私はC#部分で間違っているかもしれません。
オーバーフローはC#では無害です - あなたはメモリオーバーフローしません - あなたは単に結果の最後の8ビットを取得します。これを例外にしたい場合は、「チェックされた」キーワードを使用します。また、BYTE+BYTEがINTを与えることがあることに注意してください。そのため、BYTEに戻る必要がある場合があります。
動作は言語に依存します。
CおよびC ++では、署名されたオーバーフローは未定義であり、署名されていないオーバーフローに言及した動作があります(ただしませんが、 byte
タイプ)。
C#では、を使用できます checked
オーバーフローと unchecked
あなたがそれを無視したいと明示的に言うキーワード。
リーディングビットが落ちました。
算術的なオーバーフローが発生します。 150+199 = 349、バイナリ1 0101 1101以降、上部1ビットがドロップされ、バイトが0101 1101になります。つまり、バイトがオーバーフローを保持できます。
ダメージはありませんでした - 例: メモリー 別の場所にオーバーフローしませんでした。
C で実際に何が起こるかを見てみましょう (C には「バイト」データ型がないという指摘があるため、適切なデータ型を持っていると仮定します。ただし、追加できる 8 ビットのデータ型もあります))。これらのバイトがスタック上で宣言されている場合、それらはメイン メモリに存在します。ある時点で、バイトは処理のためにプロセッサにコピーされます (プロセッサやキャッシュなど、いくつかの重要な手順を省略しています)。プロセッサに入力されると、それらはレジスタに保存されます。プロセッサはこれら 2 つのレジスタに対して加算操作を実行して、データを加算します。 ここに混乱の原因が生じます。 CPU は、ネイティブ (または場合によっては指定された) データ型で追加操作を実行します。CPU のネイティブ タイプが 32 ビット ワードであるとします (そして、そのデータタイプが加算操作に使用されるものであるとします)。つまり、これらのバイトは、上位 24 ビットが設定されていない状態で 32 ビット ワードに格納されます。実際、加算操作ではターゲットの 32 ビット ワードでオーバーフローが行われます。ただし (ここが重要です)、データがレジスタからスタックにコピーされるとき、最下位 8 ビット (バイト) のみがスタック上のターゲット変数の位置にコピーされます。(ここでもバイト パッキングとスタックに多少の複雑さが伴うことに注意してください。)
結論は次のとおりです。加算によりオーバーフローが発生します (選択した特定のプロセッサ命令によって異なります)。ただし、データはプロセッサから適切なサイズのデータ型にコピーされるため、オーバーフローは発生しません (適切に作成されたコンパイラを想定していれば、無害です)。
C#が進む限り、タイプの2つの値を追加します byte
一緒になって、タイプの値になります int
その後、それをキャストする必要があります byte
.
したがって、コードサンプルは、以下のようにバイトに戻るキャストなしのコンパイラエラーになります。
byte byte1 = 150; // 10010110
byte byte2 = 199; // 11000111
byte byte3 = (byte)(byte1 + byte2);
詳細については、MSDNを参照してください これについて。また、を参照してください C#言語仕様, 、セクション7.3.6数値プロモーション。