I would like to have single byte with multiple funtions.
Let me explain first. Please before down voting my question, let me know what knowledge I am lacking or lagging.
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
May be 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?
CodePudding user response:
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:
- Delete any old stuff that is possibly thaer with masking
- Create value 9 and shift it to 4 positions to the right
- Delete the 4 lower bits of the shifted values
- 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
CodePudding user response:
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)