簡體   English   中英

C#:將負整數強制轉換為字節的結果

[英]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 + 255k0 ... 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上下文中發生的情況。 您可以說運行時(或編譯器,如果您在轉換時已知轉換為ByteInt32 )在需要多次時添加或減去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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM