在C#中从short转换为byte时会发生什么?

我有以下代码:

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

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

然而,它包含140,它让我想知道为什么; 幕后实际发生了什么?

请注意,我不是在找人解决23948无法容纳的问题,我只是想知道底层的实现

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 } } } 

基本上它只需要最后8位…但一般来说,当你发现一些令你惊讶的行为时,下一步应该是查阅规范。 从第6.2.1节开始,加上我的额外重点,针对与此案例相关的情况。

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

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

这取决于; 在checked上下文中,你会得到一个很大的例外; 在unchecked上下文(默认值)中,您可以保留最后一个字节中的数据,就像您执行的操作一样:

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

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

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

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

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

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

当你这样做时,结果是一样的:

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

高于八位的所有东西都被丢弃了。 23948(0x5D8C)的低8位为140(0x8C)。

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

23948%256 = 140,转换后丢失了最重要的字节,因此输出为140

这就像当你有一个两位数字,“97”,并将它转换为一位数字时,你输掉了9而只保留了“7”