[英]C#: The result of casting a negative integer to a byte
我是在查看項目的源代碼,我注意到以下語句 (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;
我的問題是:我是否應該始終期待這種情況?
是。 請記住,在.Net“字節”的域中沒有“ - ”這樣的東西:
http://msdn.microsoft.com/en-us/library/e2ayt412.aspx
因為字節是無符號類型,所以它不能表示負數。 如果對計算結果為Byte的表達式使用一元減號( - )運算符,則Visual Basic會首先將表達式轉換為Short。 (注意:用“Visual Basic”替換任何CLR / .Net語言)
ADDENDUM:這是一個示例應用程序:
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
是的,情況總是如此(即它不僅僅依賴於您的環境或編譯器,而是被定義為C#語言規范的一部分)。 請參閱http://msdn.microsoft.com/en-us/library/aa691349(v=vs.71).aspx :
在
unchecked
上下文中,通過丟棄不適合目標類型的任何高位來截斷結果。
接下來的問題是,如果你在-256和-1之間取消負int
的高位,並將其作為一個字節讀取,你會得到什么? 這是你通過實驗已經發現的:它是256 + x。
請注意,字節序無關緊要,因為我們丟棄了高階(或最高有效)位,而不是“第一”24位。 因此無論我們從哪個端點取出它,我們都留下了構成該int的最低有效字節。
這是一個算法,它執行與轉換為byte相同的邏輯,以幫助您理解它:
積極的:
byte bNum = iNum % 256;
對於否定:
byte bNum = 256 + (iNum % 256);
這就像搜索任何導致x + 255k
在0 ... 255
范圍內的k
。 只有一個k
可以產生具有該范圍的結果,結果將是轉換為字節的結果。
另一種看待它的方式就好像它“在字節值范圍內循環”:
讓我們再次使用iNum = -712
,並定義一個bNum = 0
。
我們將做iNum++; bNum--;
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.
當然,這只是一個例子,可以看出它的邏輯運作方式。
這是unchecked
上下文中發生的情況。 您可以說運行時(或編譯器,如果您在轉換時已知轉換為Byte
的Int32
)在需要多次時添加或減去256,直到找到可表示的值。
在已checked
上下文中,會產生異常(或編譯時錯誤)。 請參閱http://msdn.microsoft.com/en-us/library/khy08726.aspx
是的 - 除非你得到例外。
.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位二進制補碼有符號值”。 (嗯,這也匹配目前可用的.NET或單聲道的所有平台,所以人們幾乎可以猜測它無論如何都會起作用,但很高興知道這種做法是由語言標准和便攜式支持的。)
有些團隊不希望明確指定溢出檢查上下文,因為它們的策略是在開發周期的早期檢查溢出,而不是在已發布的代碼中檢查溢出。 在這些情況下,您可以安全地進行字節算術,如下所示
return (byte)((keyByte - codedByte) % 256);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.