1

I have 2 bytes that should populate this way:

first number (4b) second number (12b)

So 4 bit can be between 1-15 And 12 bit can be between 1-50

So i have this Bytes Array:

byte[] packetArrayBytes = new byte[Length];
user1860934
  • 417
  • 2
  • 9
  • 22
  • https://stackoverflow.com/questions/67850144/is-there-a-10-bits-unsigned-integer-data-type-in-c –  Jun 06 '21 at 11:23
  • Does this answer your question? [Define "custom" integer-based type?](https://stackoverflow.com/questions/7615113/define-custom-integer-based-type) and [How to create 24 bit unsigned integer in C](https://stackoverflow.com/questions/58010178/how-to-create-24-bit-unsigned-integer-in-c) –  Jun 06 '21 at 11:23
  • Do you mean: packetArrayBytes[0] = (byte)((someNumber >> 12) & 0xFF); packetArrayBytes[1] = (byte)((someNumber >> 4) & 0xFF); ? – user1860934 Jun 06 '21 at 11:35
  • I don't remember in detail this stuff that I haven't used for over 20 years, sorry. But indeed: you can use [bits masking](https://en.wikipedia.org/wiki/Mask_(computing)) on one value, or you can use two values embedded in a type to control each min and max with get/set as well as for example calculations. It all depends on the level of complexity and abstraction or portability of the code and the performance you want to have. –  Jun 06 '21 at 11:39

1 Answers1

1

The way I've understood the question is that you've got these two (presumably) unsigned integers a and b: (I'll be writing them in hexadecimal to make it easier to read)

a: 0x0000000X

b: 0x00000XXX

Where a is the 4-bit number and b is the 12-bit one, with the Xs marking the bits containing the relevant values.

You want to store them in two separate 8-bit chunks: c: 0x00 and d: 0x00

So you need to shift the bits into position, like this:

byte[] packetArrayBytes = new byte[2];

uint intA = 0xF;   // Allowed range is 0-15   (0x0-0xF)
uint intB = 0xABC; // Allowed range is 0-4095 (0x0-0xFFF)

// Need to convert from uint to bytes:
byte[] bytesA = BitConverter.GetBytes(intA);
byte[] bytesB = BitConverter.GetBytes(intB);
byte a = bytesA[0]; // a is 0x0F
byte b = bytesB[1]; // b is 0x0A
int c = 0x00;      // c is 0x00
int d = bytesB[0]; // d is 0xBC

// Mask out 4 least significant bits of a,
// then shift 4 bits left to place them in the most significant bits (of the byte),
// then OR them into c.
c |= (a & 0x0F) << 4;  // c is now 0xF0

// Mask out 4 least significant bits of b,
// then OR them into c.
c |= b & 0x0F;   // c is now 0xFA

packetArrayBytes[0] = (Byte)c;
packetArrayBytes[1] = (Byte)d;

Console.WriteLine(BitConverter.ToString(packetArrayBytes)); // Prints "FA-BC"

After doing these operations, the values of a and b should be placed in the bytes c and d like this: c: 0xFA d: 0xBC. Which you can then place into your array.

To get the values back you just do these same operations in reverse.

If a and b are signed values, I believe the same operations work, but you'll have to make sure you're not interpreting them as unsigned when reading the data back into numbers.

Martin Jonsson
  • 139
  • 2
  • 9
  • and how to put this into my array ? – user1860934 Jun 06 '21 at 12:36
  • `c` and `d` are the two bytes you want in the array so you should just be able to do `packetArrayBytes[0] = c;` and `packetArrayBytes[1] = d;` – Martin Jonsson Jun 06 '21 at 12:37
  • OK than ks a lot, I will try it now and update – user1860934 Jun 06 '21 at 12:38
  • In the last 3 lines (c |= (a & 0x0F) << 4; & c |= (b & 0xF00) >> 8; & d |= b & 0x0FF;) i got this compiler error: Cannot implicitly convert type 'uint' to 'byte'. – user1860934 Jun 06 '21 at 12:55
  • Ah right, this isn't C++ it's C#. My bad. You'll need to convert the `uint`s to bytes first using [BitConverter.GetBytes](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.getbytes?view=net-5.0) – Martin Jonsson Jun 06 '21 at 13:06
  • What about change byte c into uint c and then: arrayBytes[0] = (byte)a; ? – user1860934 Jun 06 '21 at 13:11
  • I've updated my solution, try that instead. – Martin Jonsson Jun 06 '21 at 13:15
  • Almost same issue: Cannot implicitly convert type 'int' to 'byte'. here: c |= (a & 0x0F) << 4; and here: c |= b & 0x0F; – user1860934 Jun 06 '21 at 13:24
  • Apparently C# does not have bitwise operators defined for `byte` so it implicitly converts them to `int`. A bit strange IMO, but easily remedied by changing a couple of the variables from `byte` to `int`. I've now tested the code myself and it runs and produces the correct output. – Martin Jonsson Jun 06 '21 at 13:33
  • For more info about these operators, I found the answers to [this question](https://stackoverflow.com/questions/3079986/why-do-cs-binary-operators-always-return-int-regardless-of-the-format-of-their) helpful. – Martin Jonsson Jun 06 '21 at 13:35
  • So in the last example what 2 numbers you choose ? 15 and 2748 ? – user1860934 Jun 06 '21 at 17:53
  • Yes, `0xF = 15` and `0xABC = 2748`. – Martin Jonsson Jun 07 '21 at 04:09