1

Using bitwise operations, is it possible to package and read back the following set of values into an uint16_t variable? I think yes but I am trying to figure out how using a sample program.

Lets say following is the set of values I want to package into an uint16_t.

unsigned int iVal1 = 165 // which is 8 bits
unsigned int iVal2 = 28  // which is 5 bits
unsigned int iVal3 = 3   // which is 2 bits
bool bVal = true;        // which can stored in 1 bit if we use 0 for true and 1 for false

Following is my program which aims to write in the values and needs to read back. How can write and read the values back using C++ 11?

#include <iostream>

uint16_t Write(unsigned int iVal1, unsigned int iVal2, unsigned int iVal3, bool bVal) {
    // Is this technique correct to package the 3 values into an uint16_t?
    return static_cast<uint16_t>(iVal1) + static_cast<uint16_t>(iVal2) + static_cast<uint16_t>(iVal3) + static_cast<uint16_t>(bVal);
}

unsigned int ReadVal1(const uint16_t theNumber) {
    // How to read back iVal1
}

unsigned int ReadVal2(const uint16_t theNumber) {
    // How to read back iVal2
}

unsigned int ReadVal3(const uint16_t theNumber) {
    // How to read back iVal3
}

bool ReadVal4(const uint16_t theNumber) {
    // How to read back bVal
}

int main() {
    unsigned int iVal1 = 165; // which is 8 bits
    unsigned int iVal2 = 28;  // which is 5 bits
    unsigned int iVal3 = 3;   // which is 2 bits
    bool bVal = true;        // which can stored in 1 bit if we use 0 for true and 1 for false

    const uint16_t theNumber = Write(iVal1, iVal2, iVal3, bVal);

    std::cout << "The first 8 bits contain the number: " << ReadVal1(theNumber) << std::endl;
    std::cout << "Then after 8 bits contain the number: " << ReadVal2(theNumber) << std::endl;
    std::cout << "Then after 2 bits contain the number: " << ReadVal3(theNumber) << std::endl;
    std::cout << "Then after 1 bit contains the number: " << ReadVal4(theNumber) << std::endl;
}
AdeleGoldberg
  • 1,289
  • 3
  • 12
  • 28

1 Answers1

2

For this, you need to play on bit shifts.

uint16_t Write(unsigned int iVal1, unsigned int iVal2, unsigned int iVal3, bool bVal) {
    // this will encode ival1 on the 8 first bits, ival2 on bits 4 to 8, 
    // ival3 on bits 2 and 3, and bval on last bit
    return (static_cast<uint16_t>(iVal1)<<8) + (static_cast<uint16_t>(iVal2)<<3) + (static_cast<uint16_t>(iVal3)<<1) + static_cast<uint16_t>(bVal);
}

Then your uint16_t will hold all the value you need. To read back, let us say ival2, you need to shift back and to use the and operator:

unsigned int ReadVal1(const uint16_t theNumber) {
    // ival1 is the first 8 bits from place 9 to 16
    uint16_t check1 = 255; // in bits 0000000011111111
    return (theNumber>>8)&check1;
}
unsigned int ReadVal2(const uint16_t theNumber) {
    // ival2 is the 5 bits from place 3 to place 8
    uint16_t check2 = 31; // in bits 0000000000011111
    return (theNumber>>3)&check2;
}
unsigned int ReadVal3(const uint16_t theNumber) {
    // ival3 is the 2 bits on places 2 and 3
    uint16_t check3 = 3; // in bits 0000000000000011
    return (theNumber>>1)&check3;
}
bool ReadVal4(const uint16_t theNumber) {
    // ival4 is the last bit
    uint16_t check4 = 1; // in bits 0000000000000001
    return theNumber&check4;
}

NB : here true is equal to 1 and false to 0.

Bibiole
  • 121
  • 8
  • 1
    Thanks a bunch. This works well! Thanks for explaining the logic in the comments. The understanding is what I was looking for along with the answer. I got it. Thanks a million! – AdeleGoldberg Jul 31 '20 at 12:28
  • Can you please explain why in the method `Write` you used `(iVal2)<<3` to set the `iVal2` in the 5 bits after the first 8? I can understand that `(iVal1)<<8` sets `iVal1` in the first 8 bits since it is using `<<8`. But how does `<<3` set `iVal2` in the next 5 bits after 8? – AdeleGoldberg Aug 04 '20 at 22:10
  • 1
    You need to count backwards. `(ival1)<<8` is not putting `ival1` on the firs 8 bits. It is freeing the last 8 ones. Same goes for `ival2`. Originally `ival2 = 00000000000XXXXX` , you want it to occupy the bits from 4 to 8. So you shift all the bits of 3 on the left `ival2<<3 = 00000000XXXXX000` – Bibiole Aug 07 '20 at 10:58