我有以下代码:
short myShort = 23948;
byte myByte = (byte)myShort;
现在我没想到myByte
包含值23948.我猜它会包含255(我相信一个字节的最大值)。
然而,它包含140,它让我想知道为什么;幕后究竟发生了什么?
请注意,我不是在找人解决23948无法容纳的问题,我只想知道底层实现
答案 0 :(得分:15)
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
}
}
}
答案 1 :(得分:6)
基本上它只需要最后8位......但总的来说,当你发现一些令你惊讶的行为时,下一步应该是参考规范。从第6.2.1节开始,特别强调我的情况,以及与此案相关的情况。
对于从整数类型到另一个整数类型的转换,处理取决于转换发生的溢出检查上下文(第7.6.12节):
- 在已检查的上下文中,如果源操作数的值在目标类型的范围内,则转换成功,但如果源操作数的值超出目标类型的范围,则抛出System.OverflowException。 / LI>
- 在未选中的上下文中,转换始终成功,并按如下方式进行。
- 如果源类型大于目标类型,则通过丢弃其“额外”最高有效位来截断源值。然后将结果视为目标类型的值。
- 如果源类型小于目标类型,则源值可以是符号扩展或零扩展,以便与目标类型的大小相同。如果源类型已签名,则使用符号扩展;如果源类型是无符号的,则使用零扩展。然后将结果视为目标类型的值。
- 如果源类型与目标类型的大小相同,则源值将被视为目标类型的值。
答案 2 :(得分:4)
取决于;在checked
上下文中,你会得到一个很大的例外;在unchecked
上下文(默认值)中,您可以保留最后一个字节的数据,就像您一样:
byte b = (byte)(value & 255);
答案 3 :(得分:3)
在您的特定情况下,当您查看值的位时,行为非常干净和干燥:
short myShort = 0x5D8C; // 23948
byte myByte = (byte)myShort; // myShort & 0xFF
Console.WriteLine("0x{0:X}", myByte); // 0x8C or 140
答案 4 :(得分:1)
仅保留最后8位。二进制23948是101110110001100b。最后8位是10001100b,等于140。
答案 5 :(得分:1)
当您将整数类型转换为“较小”整数类型时,仅考虑较小的权重位。在数学上,就好像你使用了模运算一样。所以你得到的值是140,因为23948模数256是140。
将long转换为int将使用相同的机制。
答案 6 :(得分:1)
结果如下:
byte myByte = (byte)(myShort & 0xFF);
八位之上的所有东西都被丢弃了。 23948(0x5D8C)的低8位为140(0x8C)。
答案 7 :(得分:1)
嗯......因为当你把短(2个字节)转换成字节(1个字节)时,它只得到第一个字节,而23948的第一个字节代表140个。
答案 8 :(得分:1)
23948%256 = 140,转换后丢失了最重要的字节,因此输出为140
答案 9 :(得分:1)
就像你有一个两位数的数字“97”,然后将它转换为一位数字,你就失去了9而只保留了“7”