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# 语言规范的一部分(。 请参阅 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
发生的情况。可以说运行时(或编译器,如果转换到Byte
的Int32
在编译时已知(根据需要添加或减去 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);