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?

RCIX
  • 38,647
  • 50
  • 150
  • 207
  • 1
    You need to shift 8 bits, not 4. – Ates Goral Sep 18 '09 at 04:28
  • 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 ;-p – Marc Gravell Sep 18 '09 at 04:44

6 Answers6

40

Use BitConverter

short number = 42;
byte[] numberBytes = BitConverter.GetBytes(number);
short converted = BitConverter.ToInt16(numberBytes);
TJB
  • 13,367
  • 4
  • 34
  • 46
  • Hmm didn't think of this but i like Ates' slution for now. Thanks! – RCIX Sep 18 '09 at 05:21
  • 3
    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 ; ) – TJB Sep 18 '09 at 05:44
  • 1
    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.... – Assimilater Jul 21 '17 at 15:45
  • I think BitConverter would consider big endian/little endian scenarios. – Rafael Diego Nicoletti Jan 22 '20 at 18:07
24

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);
}
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 5
    had to wrap the code in the ToShort method with a cast to short, just thought i'd let you know... – RCIX Sep 18 '09 at 04:48
  • this doesn't compile...why so many upvotes? short + short resolves to an integer operator and cannot implicitly cast int as short – Assimilater Jul 20 '17 at 19:52
  • @Assimilater In which compiler? – Ates Goral Jul 21 '17 at 14:58
  • Microsoft Visual C# compiler targeting .NETv4.5.2...does it depend on .NET version? – Assimilater Jul 21 '17 at 15:32
  • casting as a short is required in `ToShort` just before returning. See answer by @john-kugelman – Assimilater Jul 21 '17 at 16:17
  • 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 `65415` – Farid Dec 16 '21 at 14:34
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.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
4

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;
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • that taking bytes thing was actually a mistake... Good tips though, thanks! – RCIX Sep 18 '09 at 04:40
  • You'll typically want to bit shift byte2, not byte1. So something like: return (short)((byte2<<8) | byte1); – Ken Smith Oct 16 '10 at 08:00
  • though the int casts are unnecessary it shows what will happen anyways (and I think this is what you meant by the comment), so +1 – Assimilater Jul 21 '17 at 16:22
-1

System.BitConverter

  • 1
    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.. – Marc Gravell Sep 18 '09 at 04:42
  • @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... – TJB Sep 18 '09 at 04:47
  • 1
    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 ;-p – Marc Gravell Sep 18 '09 at 04:53
  • @MG when it comes to bit logic, I like to optimize for minimal bit logic ; ) But, i see your point! – TJB Sep 18 '09 at 05:10
  • @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....sigh – Assimilater Jul 21 '17 at 16:19
-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.

Finch Wang
  • 44
  • 4