【问题标题】:What happens when you cast from short to byte in C#?在 C# 中从 short 转换为 byte 时会发生什么?
【发布时间】:2011-11-26 09:36:27
【问题描述】:

我有以下代码:

short myShort = 23948;
byte myByte = (byte)myShort;

现在我没想到myByte 包含值 23948。我猜它会包含 255(我相信一个字节的最大值)。

但是,它包含 140,这让我想知道为什么;幕后究竟发生了什么?

请注意,我不是在找人来解决 23948 无法放入一个字节的问题,我只是想知道底层的实现

【问题讨论】:

    标签: c# casting byte short


    【解决方案1】:

    Short 是一个 2 字节类型,而一个字节是一个单字节。当您从两个字节转换为一个字节时,您会强制系统进行调整,并且原始字节之一(最重要的字节)被丢弃并且数据丢失。 23948(二进制:0101 1101 1000 1100)的值剩下的是 140,二进制转换为 1000 1100。所以你要从:

    0101 1101 1000 1100 (2 byte decimal value 23948)
    

    到:

              1000 1100 (1 byte decimal value 140)
    

    您只能通过显式强制转换来做到这一点。如果您尝试在不进行强制转换的情况下将短字节分配给一个字节,编译器会抛出一个错误,因为可能会丢失数据:

    无法将类型“short”隐式转换为“byte”。显式 存在转换(您是否缺少演员表?)

    另一方面,如果您将字节转换为短字节,则可以隐式执行,因为不会丢失任何数据。

    using System;
    public class MyClass
    {
        public static void Main()
        {
            short myShort = 23948;
            byte myByte = (byte)myShort; // ok
            myByte = myShort; // error: 
    
            Console.WriteLine("Short: " + myShort);
            Console.WriteLine("Byte:  " + myByte);
    
            myShort = myByte; // ok
    
            Console.WriteLine("Short: " + myShort);
        }
    }
    

    算术溢出和未经检查的上下文:

    using System;
    public class MyClass {
        public static void Main() {
            unchecked {
                short myShort = 23948;
                byte myByte = (byte)myShort; // ok
                myByte = myShort; // still an error
                int x = 2147483647 * 2; // ok since unchecked
            }   
        }
    }
    

    【讨论】:

    • 这里有一个重要的差距......即使你的样本看起来很完整,它的行为也可能不同。这取决于上下文是checked 还是unchecked,这取决于代码,还取决于编译器设置(或VS 中的“检查算术上溢/下溢”复选框)
    • Marc:我使用选中/未选中进行了测试,但对于强制转换和算术溢出,行为似乎有所不同。在未经检查的上下文中允许溢出,但强制转换仍然必须是显式的。请参阅我添加的 sn-p。 (我正在使用 .NET 3.5 运行 Snippet Compiler)所以... un/checked context 似乎对转换没有影响...
    • unchecked 是默认值;现在改成checked 看看有什么不同
    • 我都试过了。无论指定checked 还是unchedked,代码myByte = myShort; // still an error 的铸造部分的结果都是相同的。编译器错误总是一样的:Cannot implicitly convert type 'short' to 'byte'. An explicit conversion exists (are you missing a cast?)
    • 我说的唯一一行来自 OP 的帖子:byte myByte = (byte)myShort;
    【解决方案2】:

    基本上它只需要最后 8 位......但一般来说,当您发现一些让您感到惊讶的行为时,下一步应该是查阅规范。从第 6.2.1 节开始,我特别强调了与这种情况相关的情况。

    对于从一个整数类型到另一个整数类型的转换,处理取决于发生转换的溢出检查上下文(第 7.6.12 节):

    • 在检查的上下文中,如果源操作数的值在目标类型的范围内,则转换成功,但如果源操作数的值超出目标类型的范围,则抛出 System.OverflowException。
    • 在未经检查的上下文中,转换始终成功,并按如下方式进行。
      • 如果源类型大于目标类型,则源值通过丢弃其“额外”最高有效位来截断。然后将结果视为目标类型的值。
      • 如果源类型小于目标类型,则源值进行符号扩展或零扩展,使其大小与目标类型相同。如果源类型已签名,则使用符号扩展;如果源类型是无符号的,则使用零扩展。然后将结果视为目标类型的值。
      • 如果源类型与目标类型的大小相同,则源值被视为目标类型的值。

    【讨论】:

      【解决方案3】:

      视情况而定;在checked 上下文中,你会得到一个很大的异常;在unchecked 上下文(默认)中,您可以保留最后一个字节的数据,就像您这样做一样:

      byte b = (byte)(value & 255);
      

      【讨论】:

        【解决方案4】:

        在您的特定情况下,当您查看值的位时,行为非常简单:

        short myShort = 0x5D8C; // 23948
        byte myByte = (byte)myShort; // myShort & 0xFF
        
        Console.WriteLine("0x{0:X}", myByte); // 0x8C or 140
        

        【讨论】:

        • 由于没有抛出异常,我认为它是在未经检查的上下文中。
        【解决方案5】:

        只保留最后 8 位。二进制的 23948 是 101110110001100b。最后8位是10001100b,等于140。

        【讨论】:

          【解决方案6】:

          当您将整数类型转换为“较小”的整数类型时,仅考虑较小的权重位。从数学上讲,就好像您使用了模运算一样。所以你得到值 140 因为 23948 模 256 是 140。

          将 long 转换为 int 将使用相同的机制。

          【讨论】:

          • 这并不总是正确的!试试这个:short s = 35000;如果您将模 32767 计算为 2233,但编译器会根据规范分配 s -30536 ,因此这是正确的值
          • 这是因为转换为 short 与执行模 32768 (short.MaxValue + 1) 不同,而是模 65536(short 的不同值的数量)。 -30536 与 35000 模 65536 一致,并且在短值范围内。
          • 不,我认为这不正确。首先,short 不是 ushort,所以最大值是 32767;第二,35000模65535(不是65536)就是35000。我不知道,也许我理解错了什么?
          • short 有 65536 个可能的值:32767 个正数、32768 个负数和 0。因此,使用 short 的每个未经检查的计算都按照模 65536 进行操作。执行强制转换时,运行时只考虑较小的位(正如公认的答案解释得很好)。从数学上讲,这与找到范围内的全等值相同。在这种情况下,-30536,因为 35000 太大了。 (注意 -30536 + 65536 = 35000)。
          【解决方案7】:

          这样做的结果是一样的:

          byte myByte = (byte)(myShort & 0xFF);
          

          8 位以上的所有内容都被简单地丢弃。 23948(0x5D8C)的低八位是140(0x8C)。

          【讨论】:

            【解决方案8】:

            嗯...因为当你将 short(2 个字节)转换为 byte(1 个字节)时,它只得到第一个字节,而 23948 的第一个字节代表 140。

            【讨论】:

              【解决方案9】:

              23948 % 256 = 140,转换后丢失了最高有效字节,所以输出为140

              【讨论】:

                【解决方案10】:

                就像当你有一个两位数“97”,然后将其转换为一位数时,你失去了 9,只保留了“7”

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-01-12
                  • 2014-04-01
                  • 1970-01-01
                  • 2012-12-11
                  • 1970-01-01
                  • 2018-06-30
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多