我试图将一个byte[]
数组转换成sbyte[]
数组。
这是我的样例数组:
byte[] unsigned = { 0x00, 0xFF, 0x1F, 0x8F, 0x80 };
我已经尝试过这个了:
sbyte[] signed = (sbyte[])((Array)unsigned);
但这不起作用。此操作后,数组中没有任何值。
有人有更好的想法吗?
我试图将一个byte[]
数组转换成sbyte[]
数组。
这是我的样例数组:
byte[] unsigned = { 0x00, 0xFF, 0x1F, 0x8F, 0x80 };
我已经尝试过这个了:
sbyte[] signed = (sbyte[])((Array)unsigned);
但这不起作用。此操作后,数组中没有任何值。
有人有更好的想法吗?
sbyte[] signed = (sbyte[]) (Array) unsigned;
这是因为byte和sbyte在内存中的长度相同,不需要改变内存表示就可以进行转换。
然而,这种方法可能会导致调试器出现一些奇怪的错误。如果你的字节数组不是很大,你可以使用Array.ConvertAll
代替。
sbyte[] signed = Array.ConvertAll(unsigned, b => unchecked((sbyte)b));
unchecked((sbyte)b)
,这样即使启用了 checked 算术,它也能正常工作。它还可以作为文档,表明溢出是有意的,而不仅仅是性能优化。 - CodesInChaossbyte
时,使用checked算术肯定会抛出异常。可能让你感到困惑的是(byte)255 + (byte)255
不会抛出异常,因为操作数被提升为int
,在这里不会溢出。 - CodesInChaos使用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
值。
只需两行代码就可以完成,速度应该很快。
@
符号。在C#中,signed
/unsigned
不是关键字。 - CodesInChaossbyte[] signed = unsigned.Select(b=>(sbyte)b).ToArray();
我不确定语法是否正确,请检查并验证。
ConvertAll
更快,而且同样易读;2)我更喜欢unchecked((sbyte)b)
。请参见@Sepehr的答案以获取详细信息。 - CodesInChaos旧的 .net Framework 和旧的 .net Core 不支持 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();
sbyte[]
,但运行时仍然标记为byte[]
。不确定你所说的“数组中没有值”的意思,对我来说,数组是{0,-1,31,-113,-128}
,与预期相符。 - CodesInChaossbyte []
但动态类型byte []
的数组是有效的。CLR允许此转换,但C#不允许。这是一种hack,因此在大多数应用程序中,您将想使用@Selman的建议。 - CodesInChaossbyte[] signed = Array.ConvertAll(unsigned, x => unchecked((sbyte)x));
这样即使启用了带符号算术也能正常工作。 - CodesInChaos