【问题标题】:Convert byte[] to sbyte[]将 byte[] 转换为 sbyte[]
【发布时间】:2014-09-10 07:42:04
【问题描述】:

我尝试将数组从byte[] 转换为sbyte[]

这是我的示例数组:

byte[] unsigned = { 0x00, 0xFF, 0x1F, 0x8F, 0x80 };

我已经试过了:

sbyte[] signed = (sbyte[])((Array)unsigned);

但它不起作用。此操作后数组中没有值。

有人有更好的主意吗?

【问题讨论】:

  • 这段代码的工作原理是它可以编译并且不会引发错误。它生成的数组几乎在所有情况下都可以用作sbyte[],但运行时仍将其标记为byte[]。不确定“数组中没有值”是什么意思,对我来说,数组是{0, -1, 31, -113, -128},正如预期的那样。
  • 编译后签名数组中没有值。 Visual Studio 显示“?”在有符号数组的每个元素中。
  • 好的,我尝试从签名数组中获取一个元素,它仍然有效。谢谢你的帮助。我尝试使用此解决方案。
  • 那么这是 VS 的限制。 VS 可能不理解静态类型sbyte[] 但动态类型byte[] 的数组是有效的。 CLR 允许这种转换,但 C# 不允许。这是一个 hack,因此在大多数应用程序中,您需要使用 @Selman 的建议。
  • 只是调试器无法显示它,因为它实际上是 sbyte[]byte[] 的引用。

标签: c# type-conversion


【解决方案1】:
sbyte[] signed = (sbyte[]) (Array) unsigned;

之所以可行,是因为 byte 和 sbyte 在内存中具有相同的长度,并且可以在无需更改内存表示的情况下进行转换。

但是,这种方法可能会导致调试器出现一些奇怪的错误。如果你的字节数组不是很大,可以用Array.ConvertAll代替。

sbyte[] signed = Array.ConvertAll(unsigned, b => unchecked((sbyte)b));

【讨论】:

  • 我会使用 unchecked((sbyte)b) 所以即使启用了检查算术它也可以工作。它还可以作为文档说明溢出是故意的,而不仅仅是性能优化。
  • 我的记忆告诉我溢出检查不适用于字节/sbytes。我可能错了。 编辑: 现已修复 :)
  • 将 255 转换为 sbyte 肯定会引发检查算术。可能让您感到困惑的是(byte)255 + (byte)255 不会抛出,因为操作数会提升为不会溢出的int
  • 可能,我修好了它。感谢您指出这一点:)
【解决方案2】:

使用Buffer.BlockCopy怎么样?这个答案的好处是避免了逐字节的强制转换检查。这个答案的坏处是避免了逐字节进行强制检查。

var unsigned = new byte[] { 0x00, 0xFF, 0x1F, 0x8F, 0x80 };
var signed = new sbyte[unsigned.Length];
Buffer.BlockCopy(unsigned, 0, signed, 0, unsigned.Length);

这只是复制字节,byte.MaxValue 以上的值将有一个负的sbyte 值。

需要两行代码,但应该很快。

【讨论】:

  • 不需要@signed/unsigned 不是 C# 中的关键字。
  • @CodesInChaos 所以让我误入歧途。
【解决方案3】:

轻松地这样做:

sbyte[] signed = unsigned.Select(b=>(sbyte)b).ToArray();

我不确定语法。检查验证它。

【讨论】:

  • 这行得通。但是 1) ConvertAll 更快且可读性更强 2) 我更喜欢 unchecked((sbyte)b)。有关详细信息,请参阅@Sepehr 的答案。
【解决方案4】:

旧的 .net 框架和旧的 .net 核心不支持 reinterpret_cast ,但支持 * 指针和不安全代码。 新的.net版本添加system.memory库,可以解决这个问题并复制内存。

   byte[] unsigned = { 0x00, 0xFF, 0x1F, 0x8F, 0x80 };  
   ReadOnlySpan<byte> bytesBuffer = unsigned;
   ReadOnlySpan<sbyte> sbytesBuffer = MemoryMarshal.Cast<byte, sbyte>(bytesBuffer);
   sbyte[] signed = sbytesBuffer.ToArray();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-25
    • 2011-06-08
    • 2015-08-21
    • 2011-08-05
    • 2023-01-24
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多