Good way to convert between short and bytes?
Asked Answered
D

6

11

I need to take pairs of bytes in, and output shorts, and take shorts in and output pairs of bytes. Here are the functions i've devised for such a purpose:

static short ToShort(short byte1, short byte2)
{
    short number = (short)byte2;
    number <<= 4;
    number += (short)byte1;
    return number;
}
static void FromShort(short number, out byte byte1, out byte byte2)
{
    byte byte2 = (byte)(number >> 4);
    short tempByte = (short)byte2 << 4;
    byte byte1 = (byte)(number - tempByte);
}

I think this is correct but i'm not sure. If this isn't the right way to do it, what is? is there a way to do this already in the framework?

Dwanadwane answered 18/9, 2009 at 4:23 Comment(2)
You need to shift 8 bits, not 4.Outdistance
An interesting things here is that in ToShort byte1 is the MSB (i.e. the one on the left), where-as in FromShort byte1 is the LSB (i.e. the one on the right). I've switched these in my answer ;-pBrumaire
O
26

Shorter version (also shifting 8 bits instead of 4):

static short ToShort(short byte1, short byte2)
{
    return (byte2 << 8) + byte1;
}

static void FromShort(short number, out byte byte1, out byte byte2)
{
    byte2 = (byte)(number >> 8);
    byte1 = (byte)(number & 255);
}
Outdistance answered 18/9, 2009 at 4:32 Comment(6)
had to wrap the code in the ToShort method with a cast to short, just thought i'd let you know...Dwanadwane
this doesn't compile...why so many upvotes? short + short resolves to an integer operator and cannot implicitly cast int as shortHomosexuality
@Homosexuality In which compiler?Outdistance
Microsoft Visual C# compiler targeting .NETv4.5.2...does it depend on .NET version?Homosexuality
casting as a short is required in ToShort just before returning. See answer by @john-kugelmanHomosexuality
I just tested this method I don't know why it is returning wrong number after double conversion. Providing 36999 then doing FromShort and then converting it to back to short with ToShort the result becomes 65415Maunsell
C
40

Use BitConverter

short number = 42;
byte[] numberBytes = BitConverter.GetBytes(number);
short converted = BitConverter.ToInt16(numberBytes);
Curvy answered 18/9, 2009 at 4:42 Comment(4)
Hmm didn't think of this but i like Ates' slution for now. Thanks!Dwanadwane
Whatever works best for you! The upside of using a method like this is that if you have to use this code in other projects it will just be there instead of having to create a library and share code. Also, other developers can re-user their knowledge of BitConverter if they have any. Personally, we used to have some wrapper code for byte conversions we would share, but it became more of a hassle to maintain rather than just use the built in stuff. But seriously, use what works best for you ; )Curvy
As a c/c++ programmer at heart I find it silly that anyone would find it burdensome to do a simple bitshift and or operation...generating a byte[] and then however BitConverter is implemented to parse said byte[] afterwards just seems silly....Homosexuality
I think BitConverter would consider big endian/little endian scenarios.Marry
O
26

Shorter version (also shifting 8 bits instead of 4):

static short ToShort(short byte1, short byte2)
{
    return (byte2 << 8) + byte1;
}

static void FromShort(short number, out byte byte1, out byte byte2)
{
    byte2 = (byte)(number >> 8);
    byte1 = (byte)(number & 255);
}
Outdistance answered 18/9, 2009 at 4:32 Comment(6)
had to wrap the code in the ToShort method with a cast to short, just thought i'd let you know...Dwanadwane
this doesn't compile...why so many upvotes? short + short resolves to an integer operator and cannot implicitly cast int as shortHomosexuality
@Homosexuality In which compiler?Outdistance
Microsoft Visual C# compiler targeting .NETv4.5.2...does it depend on .NET version?Homosexuality
casting as a short is required in ToShort just before returning. See answer by @john-kugelmanHomosexuality
I just tested this method I don't know why it is returning wrong number after double conversion. Providing 36999 then doing FromShort and then converting it to back to short with ToShort the result becomes 65415Maunsell
B
6

If you want to take bytes... take bytes; and your shifts are off, and | would be more intuitive:

static short ToShort(byte byte1, byte byte2)
{   // using Int32 because that is what all the operations return anyway...
    return (short)((((int)byte1) << 8) | (int)byte2);
}
static void FromShort(short number, out byte byte1, out byte byte2)
{
    byte1 = (byte)(number >> 8); // to treat as same byte 1 from above
    byte2 = (byte)number;
}
Brumaire answered 18/9, 2009 at 4:35 Comment(3)
that taking bytes thing was actually a mistake... Good tips though, thanks!Dwanadwane
You'll typically want to bit shift byte2, not byte1. So something like: return (short)((byte2<<8) | byte1);Bucktooth
though the int casts are unnecessary it shows what will happen anyways (and I think this is what you meant by the comment), so +1Homosexuality
P
5

Bytes are 8 bits, not 4, so your shifting is off. You also declared local variables in the second function so you wouldn't end up writing the the out parameters like you intend. It's also clearer/better if you limit yourself to bitwise operations (&, |, and ~) where possible.

static short ToShort(byte byte1, byte byte2)
{
    return (short) ((byte2 << 8) | (byte1 << 0));
}

static void FromShort(short number, out byte byte1, out byte byte2)
{
    byte2 = (byte) (number >> 8);
    byte1 = (byte) (number >> 0);
}

Note that the left and right shifts by zero are unnecessary, strictly speaking. I just put those in for symmetry. Also, personally I'd recommend you just learn bitwise arithmetic cold and skip writing helper functions like these. No need to hide the details with something so fundamental, IMHO.

Pythian answered 18/9, 2009 at 4:31 Comment(2)
This is the only solution I'd recommend.Gwinn
This is the only solution that is correct for signed shortFarr
E
-1

System.BitConverter

Emlynne answered 18/9, 2009 at 4:39 Comment(5)
As long as you don't mind the overhead of an array all the time, and not having control over whether it it little-endian or big-endian..Brumaire
@Marc Gravell As far as having control you'll have to put in logic to handle both BE and LE right? same as reversing the array right? But i guess the array would be a slight overhead though...Curvy
By the time you've put in such logic, you might as well have just used bitwise arithmetic and avoided all the problems... if you are dealing in byte conversions, then learning a little bit-math is probably the best answer ;-pBrumaire
@MG when it comes to bit logic, I like to optimize for minimal bit logic ; ) But, i see your point!Curvy
@MarcGravell This answer...so empty...I'd downvote it but it's from a removed user so it wouldn't matter...I'd vote to remove it but it's techincally an answer....sighHomosexuality
T
-1

In .net 5/6 or .net standard 2.0+, or you can add System.Memory in Nuget if you are with .NET Fx

var body = new byte[2];
short counter = 2;
MemoryMarshal.Write(body.AsSpan(0,2), ref counter);

Now, short counter has been converted to bytes;

if you wang to convert it back, you just need

short counter = (short)(body[0] + body[1]);

That's all.

Tessi answered 21/3, 2022 at 3:41 Comment(1)
Please show a working example that converts both ways.Repository

© 2022 - 2024 — McMap. All rights reserved.