0

I would like to have single byte with multiple funtions.

I would like to split a Byte into 5 parts; that is first half byte or first four bits, with 0-15 different values.

Then the last half of the byte or last 4 bits must be separated, each bit (that is 5th, 6th, 7th, or 8th_bit) must have value of 0 or 1.

For example: if I pass value something like this "0b 1111 1 1 1 1". It should configure to the funtion which is there in value 15 of first 4 bits(0-15) and the 5th_bit(0-1) must be set(1) or clear(0) to do certain funtion and 6th, 7th, and 8th_bit must also do similar thing like 5th bit

Maybe if you look into the image you might get what I am trying to say. Please click the link to see the image. I am not sure about title, I think the title fits my question. I would like to achieve this in C++. How to achieve this? How to do this? any examples?

E_net4
  • 27,810
  • 13
  • 101
  • 139
mustaq_ahm
  • 15
  • 4
  • 2
    Have you looked into basic bitwise operators? Everything you describe is just a matter of some bit masking and bit shifting. https://en.wikipedia.org/wiki/Bitwise_operations_in_C – Robby Cornelissen Oct 12 '21 at 11:58
  • Yes, I have already saw that, but I am asking how to implement what I am supposed to do? let me know what knowledge I am lacking or lagging. – mustaq_ahm Oct 12 '21 at 12:12
  • Does this answer your question? [How to use bitmask?](https://stackoverflow.com/questions/18591924/how-to-use-bitmask) – Frebreeze Oct 12 '21 at 12:12
  • @Frebreeze that was for maniplating each bit like either 0 or 1. The link you provided will help me work with last 4 bits. But in my first 4 bits, it should have values 0 - 15. How to do that? – mustaq_ahm Oct 12 '21 at 12:28
  • IMO it's easier to move the first 4 bits to be the last, that way you can get the value using only a mask instead of shifting 4 to the right. Rest of the values are gotten anyways by masking – Eyal K. Oct 12 '21 at 12:32
  • Bitshifting is a excercise of logical comparisons typically. Get comfortable with AND, OR, XOR. Also be comfy then with binary notation and hex notation. If you want to target the leading nibble (upper 4 bits of a byte), consider a comparison like: int x = myByte & 0xF0. Or in binary notation. int x = myByte & 0b11110000. – Frebreeze Oct 12 '21 at 12:38
  • #"EyalK" #"Frebreeze" I did not get the point what your trying to say. Could you both explain in detail or maybe with example. – mustaq_ahm Oct 12 '21 at 13:00
  • See @Armin answer for a very nice breakdown of bit manipulation. – Frebreeze Oct 12 '21 at 13:35
  • @Frebreeze Yes that was nice explanation. – mustaq_ahm Oct 12 '21 at 13:44

2 Answers2

2

You need to learn a littel bit about boolean algebra. Most important are AND, OR and NOT operations. You can build anything with these 3 operations. There are other Operations which can also be used to come to any desired outcome, like NAND and NOR, and more. But anyway.

C++ has bitwise operators for AND & or OR | or NOT~. Please do not mix up with boolean logical operators &&. || and ! that work on boolean expressions.

Let us look like that bitweise operators behave. In the following example we are always talking about one sinegle bit:

AND  Result      Or   Result     NOT  Result
a b    y         a b     y       a       y
---------        ----------      ---------- 
0 0    0         0 0     0       0       1 
0 1    0         0 1     1       1       0
1 0    0         1 0     1
1 1    1         1 1     1

No we need to understand, how we can set a bit and clear a bit. From the above table you can see that

  • Something AND 0 --> is always 0. So, we can clear a bit with AND 0
  • Something OR 1 --> is always 1. So, we can set a bit with OR 1
  • Something AND 1 --> is always "Something". So, AND with 1 is a neutral operation
  • Something OR 0 --> is always "Something". So, OR with 0 is a neutral operation

OK. Now we know how to set a bit or how to clear a bit. We can also do multiple bit sets or bit clearences. So, if we want to set the uppermost 4 bits in a byte, we can write

byte = byte | 0b11110000. 

That will set the upper most 4 bits and not change the 4 lower most bits.

If we want to delete/reset/set-to-0 the bit number 0 and 1, then we can write:

byte = byte & 0b11111100. 

If we want to know the value of several bits, we can "mask" them. We can create a binary value, with bits set on positions that we want to read. Example. We want to read the 3 lower most bits.

So,

value = byte & 0b00000111. 

Should be clear now. . . .

We have also 2 additional important operations, and that is shifting. Since bits, depending on their position, have a different value, we need often to shift tehm to the correct position.

In your example, letS write the value 9 to the 4 upper most bits. What we need to do is:

  1. Delete any old stuff that is possibly thaer with masking
  2. Create value 9 and shift it to 4 positions to the right
  3. Delete the 4 lower bits of the shifted values
  4. OR the result over the target value
unsigned char value = 9;
value = value << 4;
value = value & 0b11110000;
Target = target | value;

Of course you can do all this in one statement.

Reading the 4 upper most values will be the reverse approach.

value = target & 0b11110000;
value = value >> 4;
value = value & 0b00001111;

by creating bit patterns ( a mask) you can influence all desired bits

A M
  • 14,694
  • 5
  • 19
  • 44
0

You have several way:

  • manual way, Do the bitwise operations manually, something like:

    struct S
    {
    private:
        std::byte getPage() const { return (data & 0xF0) >> 4; }
        void setPage(std::byte value) { return data = (data & 0x0F) | ((value & 0x0F) << 4); }
    
        bool getCtrl1() const { return data & 0x08; } // 1 << 3
        bool getCtrl2() const { return data & 0x04; } // 1 << 2
        bool getCtrl3() const { return data & 0x02; } // 1 << 1
        bool getCtrl4() const { return data & 0x01; } // 1 << 0
    
        void setCtrl1(bool b) { data = (data & ~0x08) | (b ? 0x08 : 0x00); }
        void setCtrl2(bool b) { data = (data & ~0x04) | (b ? 0x04 : 0x00); }
        void setCtrl3(bool b) { data = (data & ~0x02) | (b ? 0x02 : 0x00); }
        void setCtrl4(bool b) { data = (data & ~0x01) | (b ? 0x01 : 0x00); }
    
    private:
        std::byte data;
    };
    
  • use bit field:

    struct S
    {
         std::byte pages : 4;
         std::byte ctrl1 : 1;
         std::byte ctrl2 : 1;
         std::byte ctrl3 : 1;
         std::byte ctrl3 : 1;
    };
    

    (but no guaranty of order)

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I have already tried your "use bitfield" method but that dose not helped me. Also, it didnt unterstand clearly how you doing "manual way". Could you please explain manual way? – mustaq_ahm Oct 12 '21 at 12:56
  • Manual way do bit field manipulation see [Bitwise_logic_operators](https://en.cppreference.com/w/cpp/language/operator_arithmetic#Bitwise_logic_operators). – Jarod42 Oct 12 '21 at 13:23
  • Sure will look into it. – mustaq_ahm Oct 12 '21 at 13:45