15

I tried to convert an Array from byte[] to sbyte[].

Here is my sample Array:

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

I already tried this:

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

But it doesn't work. There is no value in the array after this operation.

Does anybody has an better idea?

8
  • 2
    This code works in the sense that it compiles and throws no error. It results in an array that can be used as sbyte[] in nearly every situation, but is still marked as byte[] by the runtime. Not sure what you mean by "there is no value in the array", for me the array is {0, -1, 31, -113, -128} as expected. Commented Sep 10, 2014 at 7:44
  • After compiling there is no value in the signed array. Visual Studio shows "?" in every element of the signed array. Commented Sep 10, 2014 at 7:47
  • Ok, I try to get an element from the signed array and it still works. Thanks for your help. I try to use this solution. Commented Sep 10, 2014 at 7:48
  • Then that's a VS limitation. VS might not understand that an array with static type sbyte[] but a dynamic type byte[] is valid. The CLR allows this cast, but C# does not. This is a hack, so in most applications you'll want to use @Selman's suggestion. Commented Sep 10, 2014 at 7:48
  • It's just the debugger that has problems with displaying it, as it's really a sbyte[] reference to a byte[]. Commented Sep 10, 2014 at 7:49

4 Answers 4

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

This works because byte and sbyte have the same length in memory and can be converted without the need to alter the memory representation.

This method might, however, lead to some weird bugs with the debugger. If your byte array is not very big, you can use Array.ConvertAll instead.

sbyte[] signed = Array.ConvertAll(unsigned, b => unchecked((sbyte)b)); 
Sign up to request clarification or add additional context in comments.

4 Comments

I'd use unchecked((sbyte)b) so it works even if checked arithmetic is enabled. It also serves as documentation that overflows are intentional and not just a performance optimization.
My memory told me that overflow checks do not apply to bytes/sbytes. I might have been wrong. EDIT: fixed now :)
Casting 255 to sbyte certainly throws with checked arithmetic. What might have confused you is that (byte)255 + (byte)255 does not throw, since the operands get promoted to int where it does not overflow.
Possibly, I fixed it either way. Thank you for pointing this out :)
5

How about using Buffer.BlockCopy? The good thing about this answer is that avoids cast checking on a byte by byte basis. The bad thing about this answer is that avoids cast checking on a byte by byte basis.

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

This just copies the bytes, values above byte.MaxValue will have a negative sbyte value.

Takes two lines of code but should be quick.

2 Comments

No need for the @. signed/unsigned aren't keywords in C#.
@CodesInChaos SO led me astray.
1

Easily do like this:

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

I'm not sure about syntax. check verify it.

1 Comment

This works. But 1) ConvertAll is faster and just as readable 2) I prefer unchecked((sbyte)b). See @Sepehr's answer for details.
1

old .net framework and old .net core don't support reinterpret_cast ,but support * pointer and unsafe code. new .net version add system.memory library, can solutions this question and copy memory.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.