mMilk
mMilk

Reputation: 255

C# - Bits and Bytes

I try to store some information in two bytes (byte[2]).

In the first four bit of the first byte I want to store a "type-information" encoded as a value from 0-9. And in the last four bit + the second byte I want to store a size-info, so the maximum of the size-info is 4095 (0xFFF);

Lets do some examples to explain what I mean. When type-info is 5 and the size is 963 than the result should look like: 35-C3 as hex string.

35-C3 => the 5 is the type-info and the 3C3 is the 963.

03-00 => type-info 3 and size 0.

13-00 => type-info 3 and size 1.

But I have no idea how to do this with C# and need some community help:

byte type = 5;  // hex 5
short size = 963; // hex 3C3
byte[] bytes = ???
string result = BitConverter.ToString(bytes);
// here result should by 35-C3

Upvotes: 1

Views: 735

Answers (3)

Mike Nakis
Mike Nakis

Reputation: 61949

It should look like this:

bytes = new byte[2];
bytes[0] = type << 4 | size >> 8;
bytes[1] = size & 0xff;

Note: initially my numbers were wrong, I had written type << 8 | size >> 16 while it should have been type << 4 | size >> 8 as Aleksey showed in his answer.

Comments moved into the answer for posterity:

By shifting your type bits to the left by 4 before storing them in bytes[0] you ensure that they occupy the top 4 bits of bytes[0]. By shifting your size bits to the right by 8 you ensure that the low 8 bits of size are dropped out, and only the top 4 bits remain, and these top 4 bits are going to be stored into the low 4 bits of bytes[0]. It helps to draw a diagram:

        bytes[0]                    bytes[1]
+------------------------+ +------------------------+
| 7  6  5  4  3  2  1  0 | | 7  6  5  4  3  2  1  0 |
+------------------------+ +------------------------+

  type << 4 
+-----------+
| 3  2  1  0| <-- type
+-----------+
            +------------+ +------------------------+
            |11 10  9  8 | | 7  6  5  4  3  2  1  0 | <-- size
            +------------+ +------------------------+
              size >> 8           size & 0xff

size is a 12-bit quantity. The bits are in positions 11 though 0. By shifting it right by 8 you are dropping the rightmost 8 bits and you are left with the top 4 bits only, at positions 3-0. These 4 bits are then stored in the low 4 bits of bytes[0].

Upvotes: 2

Christopher
Christopher

Reputation: 9804

Micro Optimisations of the Memory Profile for types is not something you usually should bother with in .NET. If you were running native C++ I could understand this to some degree, but I would still advise against doing that. It is a lot of work with limited benefits at best.

But in .NET you just make a class or struct with a Enumeration (Int8) "Type" and a Int16 SizeInfo, say "good enough" and call it a day. Spend your resource on something better then shaving 1 byte worth of memory off it, when 64 bit is the native Integer Size of most Computers nowadays.

BitArray is about the closest you can get to actually defining specific Bits from a byte in .NET. And it features some info on similar types.

If you want to do the math the hard way, Modulo is a good place to start.

Upvotes: 0

Aleksey
Aleksey

Reputation: 64

Try this:

byte[] bytes = new byte[2];

bytes[0] = (byte) (type << 4 | size >> 8);
bytes[1] = (byte) (size & 0xff);

Upvotes: 2

Related Questions