在 C# 中从短整型转换为字节时会发生什么?

发布于 2024-12-07 00:15:42 字数 266 浏览 1 评论 0原文

我有以下代码:

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

现在我并不期望 myByte 包含值 23948。我猜测它会包含 255(我相信一个字节的最大值)。

然而,它包含了140个,这让我想知道为什么;幕后到底发生了什么?

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

I have the following code:

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

Now I wasn't expecting myByte to contain the value 23948. I would have guessed that it would contain 255 (I believe the largest value for a byte).

However, it contains 140, and it made me wonder why; what is actually going on behind the scenes?

Please note that I am not looking for someone to solve the problem that 23948 cannot fit into a byte, I am merely wondering about the underlying implementation

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

瀟灑尐姊 2024-12-14 00:15:42

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

Short is a 2-byte type and a byte is, well, a single byte. When you cast from two bytes to one you're forcing the system to make things fit and one of the original bytes (the most significant) gets dropped and data is lost. What is left from the value of 23948 (binary: 0101 1101 1000 1100) is 140 which in binary translates to 1000 1100. So you are going from:

0101 1101 1000 1100 (2 byte decimal value 23948)

to:

          1000 1100 (1 byte decimal value 140)

You can only do this with an explicit cast. If you tried assigning a short to a byte without a cast the compiler would throw an error because of the potential for loss of data:

Cannot implicitly convert type 'short' to 'byte'. An explicit
conversion exists (are you missing a cast?)

If you cast from a byte to a short on the other hand you could do it implicitly since no data would be getting lost.

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

With arithmetic overflow and unchecked context:

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
        }   
    }
}
翻身的咸鱼 2024-12-14 00:15:42

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

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

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

Basically it just takes the last 8 bits... but in general, when you find some behaviour which surprises you, the next step should be to consult the spec. From section 6.2.1, with the extra emphasis mine, for the situation which is relevant in this case.

For a conversion from an integral type to another integral type, the processing depends on the overflow checking context (§7.6.12) in which the conversion takes place:

  • In a checked context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws a System.OverflowException if the value of the source operand is outside the range of the destination type.
  • In an unchecked context, the conversion always succeeds, and proceeds as follows.
    • If the source type is larger than the destination type, then the source value is truncated by discarding its “extra” most significant bits. The result is then treated as a value of the destination type.
    • If the source type is smaller than the destination type, then the source value is either sign-extended or zero-extended so that it is the same size as the destination type. Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. The result is then treated as a value of the destination type.
    • If the source type is the same size as the destination type, then the source value is treated as a value of the destination type.
旧故 2024-12-14 00:15:42

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

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

It depends; in a checked context, you'll get a big fat exception; in an unchecked context (the default) you get to keep the data from the last byte, the same as if you did:

byte b = (byte)(value & 255);
半枫 2024-12-14 00:15:42

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

short myShort = 0x5D8C; // 23948
byte myByte = (byte)myShort; // myShort & 0xFF

Console.WriteLine("0x{0:X}", myByte); // 0x8C or 140

In your specific case, the behavior is pretty cut and dry when you look at the bits for the value:

short myShort = 0x5D8C; // 23948
byte myByte = (byte)myShort; // myShort & 0xFF

Console.WriteLine("0x{0:X}", myByte); // 0x8C or 140
春庭雪 2024-12-14 00:15:42

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

Only the last 8 bits are kept. 23948 in binary is 101110110001100b. The last 8 bits of that is 10001100b, which equals 140.

听,心雨的声音 2024-12-14 00:15:42

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

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

When you cast an integer type to a "smaller" integer type, only the lesser weight bits are considered. Mathematically, it's as if you used the modulo operation. So you get the value 140 because 23948 modulo 256 is 140.

Casting a long to an int would use the same mechanism.

星星的軌跡 2024-12-14 00:15:42

这样做的结果是一样的:

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

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

The result is the same when you do:

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

Everything above the eight bit is simply thrown away. The lower eight bits of 23948 (0x5D8C) is 140 (0x8C).

时光倒影 2024-12-14 00:15:42

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

Uhm...because when you cast short (2 bytes) to byte (1 byte) it gets only the first byte, and, the first byte of 23948 represents 140.

残疾 2024-12-14 00:15:42

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

23948 % 256 = 140, most significant bytes was lost after conversion, so the output is 140

指尖凝香 2024-12-14 00:15:42

就像当你有一个两位数“97”,并将其转换为一位数时,你会丢失 9 并只保留“7”

It's like when you have a two digit number, "97", and convert it to a one digit number, you lose the 9 and only keep the "7"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文