2012-05-13 105 views
10

負整數的結果我是在看的a project的源代碼,我注意到以下statement(二者keyByte和codedByte是byte類型):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「字節」的範圍之內,.Net將首先提升(大於255的整數值)。 – paulsm4

回答

4

是的,這將永遠是這種情況(即它不是簡單地依賴於您的環境或編譯器,而是定義爲C#語言規範的一部分)。見http://msdn.microsoft.com/en-us/library/aa691349(v=vs.71).aspx

unchecked上下文中,結果通過丟棄不符合目標類型的任何高序位截斷。

下一個問題是,如果你拿走的-256和-1之間的負int高階位,讀它作爲一個字節,你怎麼弄?這是你通過實驗已經發現的:它是256 + x。

請注意,字節順序並不重要,因爲我們丟棄了高位(或最高位)的位,而不是「第一位」的24位。所以不管我們從哪個端點取得它,我們都留下了組成該int的最低有效字節。

+0

出於好奇,如果您的硬件(CPU)使用除二進制補碼錶示的整數以外的其他東西,該怎麼辦?爲了得到這個答案,我們需要去CLR規範而不是C#規範。 ECMA335第12.1節將'int'標識爲「32位2的補碼有符號值」。這些都僅僅是理論,因爲.NET(或者單聲道)目前運行的硬件範圍有限,但它是我們被問到的問題的最終答案。是的,負值不能給出任何數值上不同的結果,即使在假設的未來硬件上也是如此。 –

+0

出於好奇,如果恐龍永遠不會絕跡?我們會用翼手術而不是發明噴氣飛機嗎?爲什麼不給這個簡單的事實莫塔信用,這是絕對和完全正確的:'對於任何.Net語言,對於有符號整數值-256 paulsm4

+0

對於nonce :[有從字節到短,ushort,int,uint,long,ulong,float,double或decimal的預定義隱式轉換。](http://msdn.microsoft.com/zh-cn/library/5bdb6693% 28V = vs.71%29.aspx) – paulsm4

4

是的。請記住,有沒有這樣的事情「 - 」在.NET「字節」的域名:

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

因爲它是無符號的類型,它不能代表一個負 數。如果在 求值爲鍵入字節的表達式上使用一元減號( - )運算符,則Visual Basic首先將表達式轉換爲簡寫爲 。 (注:替換任何CLR/.NET語言的 「Visual Basic中」)

附錄: 下面是一個示例應用程序:

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',其中'b'是'byte',它會首先將它轉換爲'short'。 –

+0

你能給一個參考嗎? ECMA 334(14.7)似乎只承認「int」,「uint」,「long」,「ulong」等算術。這並不是說它非常相關,但我們中的一個在細節上是錯誤的,我很好奇這是誰。 –

+0

我不知道Visual Basic是做什麼的,但這不是C#規範在4.5.1節中所說的:「對於一元運算符,操作數轉換爲T類型,其中T是第一個int和long可以完全表示操作數的所有可能值。「在這種情況下,該類型是int。此外,二進制 - 也轉換爲int以及字節。 –

0

這是unchecked上下文中發生的情況。你可以說運行時(或者編譯器,如果你在上輸入的Int32在編譯時是已知的),會根據需要增加或減少256次,直到找到可表示的值。

checked上下文中,會產生異常(或編譯時錯誤)。請參閱http://msdn.microsoft.com/en-us/library/khy08726.aspx

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.

無論硬件如何represents signed values這是如此。 CLR標準(ECMA 335)在第12.1節中規定,Int32類型是「32位二進制補碼有符號值」。 (嗯,它也匹配所有平臺上的.NET或mono目前可用,所以人們幾乎可以猜測它會工作,但它是很好的知道這種做法是由語言標準和便攜式支持。)

有些團隊不希望明確指定溢出檢查上下文,因爲他們有一個在開發週期早期檢查溢出的策略,而不是在已發佈的代碼中。在這種情況下,你可以放心地做字節算術這樣的:

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

這裏是執行相同的邏輯鑄造成字節的算法,以幫助您理解它:

爲陽性:

byte bNum = iNum % 256; 

對於底片:

byte bNum = 256 + (iNum % 256); 

這就像搜索任何k這導致x + 255k在範圍0 ... 255。只能有一個k產生一個範圍的結果,結果將是轉換爲字節的結果。

看它的另一種方式是,如果它「周圍的字節值範圍循環」:

允許再次使用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. 

這當然只是一個例證,看看它是如何工作的邏輯。