2012-05-13 17 views
10

に負の整数を鋳造した結果Iはa projectのソースコードを見ていた、私は(keyByteとcodedByte両方のタイプbyteである)以下statementに気づい:C番号:バイト

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; 

私の質問は:私はいつもそうであると思いますか?

+0

繰り返し:あなたは間違いなしです。 "負"の値は.Net "byte"のドメイン外にあるため、.Netは最初に(255より大きな整数値に)昇格します。 – paulsm4

答えて

4

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

unchecked文脈では、結果は、先の型に収まらない任意の上位ビットを破棄することによって切り捨てられます。

次の質問は、あなたが-256と-1との間に負のintの上位ビットを奪うと、バイトとしてそれを読めば、あなたは何を得るか、ですか?これはあなたが既に実験によって発見したものです:256 + xです。

「最初の」24ビットではなく、上位(または最上位)ビットを破棄しているので、エンディアンは問題ではありません。したがって、どちらの終わりにしても、それを構成する最下位バイトが残っています。

+0

あなたのハードウェア(CPU)が整数の2の補数バイナリ表現以外のものを使用している場合はどうなのですか?これに答えるには、C#の仕様ではなくCLRの仕様に進む必要があります。 ECMA335、セクション12.1は、「int」を「32ビットの2の補数の符号付き値」として識別します。これは、.NET(またはモノ)が現在実行されているハードウェアの限られた範囲の理論だけですが、質問された質問に対する最終的な答えです。はい、負の値は数値的に異なる結果を与えることはできません。 –

+0

恐竜から、恐竜が決して絶滅しなかったらどうなるでしょうか?私たちはジェット機を発明するのではなく、奇形を飛ぶでしょうか?なぜ、これは絶対的かつ完全に正しいという単純な事実のためにMotaに信用を与えるだけではありません: '.Net言語の場合、符号付き整数値の場合-256 paulsm4

+0

nonce :[バイトからshort、ushort、int、uint、long、ulong、float、double、またはdecimalの間で事前定義された暗黙の変換があります。](http://msdn.microsoft.com/en-us/library/5bdb6693% 28v = vs.71%29.aspx) – paulsm4

4

はい。

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

バイトが符号なしの型であるので、それは負の 数を表すことはできません: - 「」ネット「バイト」のドメインでのようなものはありません、覚えておいてください。 がByte型を評価する式で単項マイナス( - )演算子を使用する場合、Visual Basicは式を短く に変換します。 (注: "Visual Basicの" のために任意の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 
+1

私は、負の整数からバイトへのキャスティングが常に同じかどうか、という懸念には言及していないので、これを下げました。 'b 'が' byte'であるところの '-b'と言うと、それを最初に' short'に変換することを知っているが、完全に分かれています。 –

+0

参考にできますか? ECMA 334(14.7)は、「int」、「uint」、「long」、「ulong」でのみ算術を認識しているようです。それはここではとても重要なことではありませんが、私たちのうちの一人が細部に間違っていて、私はそれが誰なのか不思議です。 –

+0

Visual Basicが何をしているのか分かりませんが、C#仕様のセクション4.5.1で述べられているとおりではありません: "単項演算子の場合、オペランドはT型に変換されます。オペランドのすべての可能な値を完全に表すことができます。この場合、その型はintです。また、バイナリ - バイトにもintに変換されます。 –

0

これはuncheckedのコンテキストで発生します。実行時(つまり、ByteにキャストしたInt32がコンパイル時に判明している場合はコンパイラ)は、表現可能な値を見つけるまで、必要な回数256を加算または減算します。

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

0

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

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

整数型から別の整数型への変換では、変換結果はオーバーフローチェックコンテキスト(ECMA 334標準、13.2.1項を参照)に依存します。

ので、次のコンテキスト

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

にあなたはSystem.OverflowExceptionが表示されます。次のコンテキストでのに対し:

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

あなたはいつもあなたは関係なく、あなたがまたは差に256の倍数を追加していないかどうかの期待する結果を見ることが保証されています。例えば、2 - 255 = 3である。ハードウェアrepresents signed valuesに関係なく、これは当てはまる。 CLR標準(ECMA 335)は、12.1.1項でInt32タイプが「32ビットの2の補数の符号付き値」であることを指定しています。 (まあ、それは.NETやモノが現在利用可能なすべてのプラットフォームにもマッチするので、とにかく動作するとは思うかもしれませんが、言語標準とポータブルでサポートされていることを知っておいてください)

一部のチームでは、開発サイクルの早い段階でオーバーフローをチェックするポリシーがあるため、リリースされたコードではチェックされないため、オーバーフローチェックコンテキストを明示的に指定したくないチームもあります。ここで

return (byte)((keyByte - codedByte) % 256); 
3

あなたがそれを理解するために、byteにキャストするのと同じロジックを実行するアルゴリズムである:

陽性の場合:

byte bNum = iNum % 256; 
これらのケースでは、あなたが安全に、このようなバイト演算を行うことができますネガの場合

byte bNum = 256 + (iNum % 256); 

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

再び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. 

これは、もちろん、それがどのように動作するか、論理的に参照するには、単に例示です。