C#:将负整数强制转换为字节的结果

本文关键字:转换 字节 结果 整数 | 更新日期: 2023-09-27 18:34:06

我正在查看一个项目的源代码,我注意到以下语句(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;

我的问题是:我应该总是期望是这种情况吗?

C#:将负整数强制转换为字节的结果

是的,情况总是如此(即它不仅仅依赖于您的环境或编译器,而是定义为 C# 语言规范的一部分(。 请参阅 http://msdn.microsoft.com/en-us/library/aa691349(v=vs.71(.aspx:

unchecked上下文中,通过丢弃不适合目标类型的任何高阶位来截断结果。

下一个问题是,如果你去掉 -256 和 -1 之间的负int的高阶位,并将其读取为一个字节,你会得到什么? 这是你通过实验已经发现的:它是256 + x。

请注意,字节序无关紧要,因为我们丢弃的是高阶(或最重要的(位,而不是"第一个"24 位。 因此,无论我们从哪一端取它,我们都会留下构成该整数的最低有效字节。

是的。 请记住,在 .Net "Byte" 的域中没有"-"这样的东西:

http://msdn.microsoft.com/en-us/library/e2ayt412.aspx

由于 Byte 是无符号类型,因此它不能表示负数 数。如果对表达式使用一元减号 (-( 运算符 计算为类型字节,Visual Basic 将表达式转换为短整型 第一。(注意:用任何CLR/.Net语言代替"Visual Basic"(

补遗:下面是一个示例应用:

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

下面是一个执行与转换为字节相同的逻辑的算法,以帮助您理解它:

对于积极因素:

byte bNum = iNum % 256;

对于底片:

byte bNum = 256 + (iNum % 256);

这就像搜索导致x + 255k在范围内的任何k 0 ... 255 .只能有一个k生成该范围的结果,结果将是转换为字节的结果。

另一种看待它的方式是,就好像它"绕字节值范围循环":

让我们再次使用该iNum = -712,并定义一个bNum = 0

我们将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 或 mono 的所有平台,所以人们几乎可以猜到它无论如何都可以工作,但很高兴知道这种做法受到语言标准和可移植性的支持。

某些团队不希望显式指定溢出检查上下文,因为他们的策略是在开发周期的早期检查溢出,而不是在已发布的代码中检查溢出。 在这些情况下,您可以像这样安全地进行字节运算:

return (byte)((keyByte - codedByte) % 256);