11

プロジェクトのソースコードを見ていたら、次のステートメントに気づきました(keyByteとcodedByteはどちらもタイプですbyte)。

return (byte)(keyByte - codedByte);

keyByteがcodedByteよりも小さく、負の整数になる場合の結果を理解しようとしています。

[-255:-1]の範囲の値を持つ負の整数をキャストした結果を理解するためのいくつかの実験の後、次の結果が得られました。

byte result = (byte) (-6);  // result = 250
byte result = (byte) (-50); // result = 206
byte result = (byte) (-17); // result = 239
byte result = (byte) (-20); // result = 236

したがって、その-256 < a < 0場合、次の方法で結果を判断できました。

result = 256 + a;

私の質問は、これが事実であると常に期待すべきかということです。

4

5 に答える 5

5

はい。.Net「バイト」のドメインには「-」のようなものはないことを忘れないでください。

http://msdn.microsoft.com/en-us/library/e2ayt412.aspx

バイトは符号なしタイプであるため、負の数を表すことはできません。Byte型と評価される式で単項マイナス(-)演算子を使用すると、VisualBasicは最初に式をShortに変換します。(注:「VisualBasic」の代わりにCLR / .Net言語を使用してください)

補遺:サンプルアプリは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestByte
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = -255; i < 256; i++)
            {
                byte b = (byte)i;
                System.Console.WriteLine("i={0}, b={1}", i, b);
            }
        }
    }
}

結果の出力は次のとおりです。

testbyte|more
i=-255, b=1
i=-254, b=2
i=-253, b=3
i=-252, b=4
i=-251, b=5
...
i=-2, b=254
i=-1, b=255
i=0, b=0
i=1, b=1
...
i=254, b=254
i=255, b=255
于 2012-05-13T20:08:54.737 に答える
5

はい、常にそうです (つまり、単に環境やコンパイラに依存するのではなく、C# 言語仕様の一部として定義されています)。http://msdn.microsoft.com/en-us/library/aa691349(v=vs.71).aspxを参照してください。

コンテキストでは、unchecked結果は、宛先の型に適合しない上位ビットを破棄することによって切り捨てられます。

次の質問は、-256 と -1 の間の負の上位ビットをint取り除いてバイトとして読み取ると、何が得られるかということです。これは、実験ですでにわかっていることです: 256 + x です。

「最初の」24ビットではなく、上位(または最上位)ビットを破棄しているため、エンディアンは重要ではないことに注意してください。したがって、どちらの端から取得したかに関係なく、その int を構成する最下位バイトが残ります。

于 2012-05-13T20:33:53.230 に答える
3

理解を助けるために、バイトへのキャストと同じロジックを実行するアルゴリズムを次に示します。

肯定的な場合:

byte bNum = iNum % 256;

ネガの場合:

byte bNum = 256 + (iNum % 256);

これは、範囲内にkあるものを検索するようなものです。その範囲で結果を生成するのは1 つだけであり、その結果はバイトへのキャストの結果になります。x + 255k0 ... 255k

それを見る別の方法は、「バイト値の範囲を循環する」かのようです。

再び を使用してiNum = -712、 を定義しましょうbNum = 0

iNum++; bNum--;までやりますiNum == 0

iNum = -712;
bNum = 0;

iNum++; // -711
bNum--; // 255 (cycles to the maximum value)

iNum++; // -710
bNum--; // 254

... // And so on, as if the iNum value is being *consumed* within the byte value range cycle.

もちろん、これは論理的にどのように機能するかを示すための単なる例です。

于 2012-05-13T20:22:09.520 に答える
0

これはunchecked文脈で起こることです。ランタイム (またはコンパイル時Int32にキャスト先Byteがわかっている場合はコンパイラ) は、表現可能な値が見つかるまで、必要な回数だけ 256 を加算または減算すると言えます。

コンテキストではchecked、例外 (またはコンパイル時エラー) が発生します。http://msdn.microsoft.com/en-us/library/khy08726.aspxを参照してください。

于 2012-05-13T20:20:18.647 に答える
0

はい - 例外が発生しない限り。

.NET は、すべての算術演算を 4 バイト以上のデータ型に対してのみ定義します。したがって、唯一の非自明な点は、 を に変換する方法intですbyte

整数型から別の整数型への変換の場合、変換の結果はオーバーフロー チェック コンテキストに依存します (ECMA 334 標準、セクション 13.2.1 による)。

したがって、次のコンテキストでは

checked
{
    return (byte)(keyByte - codedByte);
}

が表示されますSystem.OverflowException。一方、次のコンテキストでは:

unchecked
{
    return (byte)(keyByte - codedByte);
}

差に 256 の倍数を追加するかどうかに関係なく、常に期待どおりの結果が得られることが保証されます。たとえば、2 - 255 = 3 です。

これは、ハードウェア が符号付きの値をどのように表現するかに関係なく当てはまります。CLR 標準 (ECMA 335) は、セクション 12.1 で、Int32型が「32 ビットの 2 の補数の符号付き値」であることを指定しています。(まあ、これは現在 .NET または mono が利用可能なすべてのプラットフォームとも一致するため、いずれにせよ機能するとほぼ推測できますが、この方法が言語標準でサポートされており、移植可能であることを知っておくとよいでしょう。)

一部のチームは、開発サイクルの早い段階でオーバーフローをチェックするポリシーを持っているが、リリースされたコードではオーバーフローをチェックしていないため、オーバーフロー チェック コンテキストを明示的に指定したくない場合があります。このような場合、次のようにバイト演算を安全に実行できます。

return (byte)((keyByte - codedByte) % 256);
于 2012-05-13T20:20:32.743 に答える