How can I remove a flag in C? - c

There is a variable that holds some flags and I want to remove one of them. But I don't know how to remove it.
Here is how I set the flag.
my.emask |= ENABLE_SHOOT;

Short Answer
You want to do an Bitwise AND operation on the current value with a Bitwise NOT operation of the flag you want to unset. A Bitwise NOT inverts every bit (i.e. 0 => 1, 1 => 0).
flags = flags & ~MASK; or flags &= ~MASK;.
Long Answer
ENABLE_WALK = 0 // 00000000
ENABLE_RUN = 1 // 00000001
ENABLE_SHOOT = 2 // 00000010
ENABLE_SHOOTRUN = 3 // 00000011
value = ENABLE_RUN // 00000001
value |= ENABLE_SHOOT // 00000011 or same as ENABLE_SHOOTRUN
When you perform a Bitwise AND with Bitwise NOT of the value you want unset.
value = value & ~ENABLE_SHOOT // 00000001
you are actually doing:
0 0 0 0 0 0 1 1 (current value)
& 1 1 1 1 1 1 0 1 (~ENABLE_SHOOT)
---------------
0 0 0 0 0 0 0 1 (result)

my.emask &= ~(ENABLE_SHOOT);
to clear a few flags:
my.emask &= ~(ENABLE_SHOOT|SOME_OTHER|ONE_MORE);

It's important to note that if the variable being manipulated is larger than an int, the value used in the 'and not' expression must be as well. Actually, one can sometimes get away with using smaller types, but there are enough odd cases that it's probably best to use type suffixes to make sure the constants are large enough.

Related

~ Unary Operator and Bitwise Tests Give Negative Results

I was studying bitwise operators and they make sense until the unary ~one's complement is used with them. Can anyone explain to me how this works?
For example, these make sense however the rest of the computations aside from these do not:
1&~0 = 1 (~0 is 1 -> 1&1 = 1)
~0^~0 = 0 (~0 is 1 -> 1^1 = 0)
~1^0 = 1 (~1 is 0 -> 0^1 = 1)
~0&1 = 1 (~0 is 1 -> 1&1 = 1)
~0^~1 = 1 (~0 is 1, ~1 is 0 -> 1^0 = 1)
~1^~1 = 0 (~1 is 0 -> 0^0)
The rest of the results produced are negative(or a very large number if unsigned) or contradict the logic I am aware of. For example :
0&~1 = 0 (~1 = 0 therefor 0&0 should equal 0 but they equal 1)
~0&~1 = -2
~1|~0 = -1
etc. Anywhere you can point me to learn about this?
They actually do make sense when you expand them out a little more. A few things to be aware of though:
Bitwise AND yields a 1 only when both bits involved are 1. Otherwise, it yields 0. 1 & 1 = 1, 0 & anything = 0.
Bitwise OR yields a 1 when any of the bits in that position are a 1, and 0 only if all bits in that position are 0. 1 | 0 = 1, 1 | 1 = 1, 0 | 0 = 0.
Signed numbers are generally done as two's complement (though a processor does not have to do it that way!). Remember with two's complement, you invert and add 1 to get the magnitude when the highest bit position is a 1.
Assuming a 32-bit integer, you get these results:
0 & ~1 = 0 & 0xFFFFFFFE = 0
~0 & ~1 = 0xFFFFFFFF & 0xFFFFFFFE = 0xFFFFFFFE (0x00000001 + 1) = -2
~1 | ~0 = 0xFFFFFFFE & 0xFFFFFFFF = 0xFFFFFFFF (0x00000000 + 1) = -1
0&~1 = 0 (~1 = 0 therefor 0&0 should equal 0 but they equal 1)
~1 equals -2. If you flip all the bits of a Two's Complement number, you multiply it by -1 and subtract 1 from the result. Regardless of that 0 has 0 for all the bits, so the result of & is going to be 0 anyway.
~0&~1 = -2
~0 has all bits set so ~0&~1 is just ~1. Which is -2.
~1|~0 = -1
~0 has all bits set, so the result of the | is ~0 (= -1) no matter what it is OR'd with.
~1 = 0 - No it's not. It's equal to -2. Let's take a eight bit two complement as example. The decimal number 1 has the representation 0000 0001. So ~1 will have 1111 1110 which is the two complement representation of -2.

How are the individual bits accessed in this code?

So I saw this code which printed out individual bits of any number.I do not understand why the individual bits are accessed and not the entire number itself
#include <stdio.h>
int main()
{
int x=10, b;
for(b=0; x!=0; x>>=1) {
printf("%d:%d\n", b, (x&1));
b++;
}
}
OUTPUT:
0:0
1:1
2:0
3:1
Please help me understand this piece of code.
In your code you are printing the value of X variable in binary. For this, your code, use logical operation as AND operator and right-shift.
In the loop condition, you displace the X variable one bit to the right.
for b = 0 you get x = 1010
for b = 1 you get x = 101
for b = 2 you get x = 10
for b = 3 you get x = 1
Then, in your print, show your loop iterator (b) and your X variable AND 1.
The AND operator get this values:
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1
In your case, you have:
1010 AND (000)1 = 0
101 AND (00)1 = 1
10 AND (0)1 = 0
1 AND 1 = 1
There are two questions in your post: how to access an individual bit ? and how to select that bit ?
Concerning the first question, suppose you want to access the less significant bit (or, to make it simpler, the rightmmost bit), you can use a mask: suppose your data is b0011 for instance, you can mask with b0001 (i.e. 1 in decimal).
0 0 1 1
& 0 0 0 1
---------
0 0 0 1
The & operator is the bitwise and. If you look in your code sample, you have printf("%d:%d\n", b, (x&1)); in which you can see x & 1, i.e. print the rightmost bit of x.
Now comes the second question: how to put each bit in the rightmost position one after each other (said otherwise, how to select the bit to print) ? An easy solution is to shift your data of 1 position to the right each time you want to select the next bit (i.e. the bit to the left of the current one).
In C, you can shift using >>. For instance, if x is b0011, then x >> 1 is b0001 (in this case, you fill the leftmost position with zeros, but in some cases it might be trickier). If you look in you code sample, you have x>>=1 in the for-loop, which assigns x >> 1 in x.
Hence, suppose you take the previous example:
0 0 1 1 = x 0 0 0 1 = x
& 0 0 0 1 & 0 0 0 1
--------- x >> 1 = b0001 -> x ---------
0 0 0 1 0 0 0 1
and so one...
A last bonus point, the loop stopping condition is x != 0, this implies that you don't prints all bits of your data, but only the bits up to the leftmost 1 (included). For instance, in the above example, after printing the two rightmost bits, x becomes 0 and the loop exits.

How to randomly pick a value based on the position of the bit

Is there a way to pick a value based on the bit position. The problem statement is:-
for a 16 bits position, I can set any bits, say I set 1,4,6,7,11,13 bit
so the mask would be:-
Bit Positons 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0
Now I need to randomly pick a value based on this bit mask, where only 1 bit is set, so my possible values could be:-
For selecting 4 :0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
For Selecting 7: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
But I need to select this value randomly, so I though of doing it like this
1)Create an Array based on the bit mask, so for 16 bit , the array would have 16 unique values.
2) Now do the rand operation on the array position to get the array index.
3) Use the value at that array index.
Is there a better way of doing it?
If I understand correctly you want a number with exactly one bit set that is also set in the mask.
To do this I'd make a while loop that selects a random value between 0 and 16 until it has found one that is also set in the mask:
uint16_t mask = 0x28d2; /* == 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0 */
int bit = 0;
do{
bit = 1 << (rand() % 16); /* sets one random bit between 1 and 16 */
}while(!(mask & bit));
/* bit has now exactly one bit set that is also set in mask */
If the goal is to have a value with at most one bit set at the end, you don't need the array. You can simply randomly generate a value between 0-15, then bitshift 1 left by that value to get the mask that you will use to select the bit, like this:
uint16_t myValue = 0xA5;
int shiftValue = rand() % 16;
uint16_t randomMask = 1u << shiftValue;
uint16_t randomValue = myValue & randomMask;
If you instead need a value with exactly one of the bits set at the end, it gets a little trickier. At that point, you could do more or less what you said and use an array to store the positions of the bits that are set (e.g. [1, 4, 6, 7, 11, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], using zeroes to indicate when there are no more bits set), then generate a random index into the portion of the array containing valid indices. There are certainly other ways to do it too, but this way seems like one that will be fairly clear to future readers of the code (though I would still comment this somewhat carefully, since bit operations can get confusing fast).
(BTW, there are much better ways of generating random numbers than rand(), and you should probably use one of those if you need anything approaching real randomness - I just used it here as a convenient shorthand, since the actual RNG doesn't matter.)
You can do that in this way:
bitMask = 0x28d2;
randomNum = rand() % 16;
randomBit = (1<<randomNum) & bitMask;
If you want exactly one bit set, you could use a re-try loop, or something like this: (add the appropriate definitions and maybe add a special case for mask == 0)
while (mask)
{
array[i++] = mask & -mask;
mask &= mask - 1;
}
return array[rand_in_range(0, i)];
Where rand_in_range(a, b) is a function that returns a random number in the range [a, b> (be careful with that, 99% of the implementations of rand_in_range are incorrect while seeming correct in most tests, the worst kind of bug).

Changing the LSB to 1 in a 4 bit integer via C

I am receiving a number N where N is a 4-bit integer and I need to change its LSB to 1 without changing the other 3 bits in the number using C.
Basically, all must read XXX1.
So lets say n = 2, the binary would be 0010. I would change the LSB to 1 making the number 0011.
I am struggling with finding a combination of operations that will do this. I am working with: !, ~, &, |, ^, <<, >>, +, -, =.
This has really been driving me crazy and I have been playing around with >>/<< and ~ and starting out with 0xF.
Try
number |= 1;
This should set the LSB to 1 regardless of what the number is. Why? Because the bitwise OR (|) operator does exactly what its name suggests: it logical ORs the two numbers' bits. So if you have, say, 1010b and 1b (10 and 1 in decimal), then the operator does this:
1 0 1 0
OR 0 0 0 1
= 1 0 1 1
And that's exactly what you want.
For your information, the
number |= 1;
statement is equivalent to
number = number | 1;
Use x = x | 0x01; to set the LSB to 1
A visualization
? ? ? ? ? ? ? ?
OR
0 0 0 0 0 0 0 1
----------------------
? ? ? ? ? ? ? 1
Therefore other bits will stay the same except the LSB is set to 1.
Use the bitwise or operator |. It looks at two numbers bit by bit, and returns the number generated by performing an OR with each bit.
int n = 2;
n = n | 1;
printf("%d\n", n); // prints the number 3
In binary, 2 = 0010, 3 = 0011, and 1 = 0001
0010
OR 0001
-------
0011
If n is not 0
n | !!n
works.
If n is 0, then !n is what you want.
UPDATE
The fancy one liner :P
n = n ? n | !!n : !n;

How to replace bits in a bitfield without affecting other bits using C

I wanted to replace bit/bits (more than one) in a 32/64 bit data field without affecting other bits. Say for example:
I have a 64-bit register where bits 5 and 6 can take values 0, 1, 2, and 3.
5:6
---
0 0
0 1
1 0
1 1
Now, when I read the register, I get say value 0x146 (0001 0 10 0 0110). Now I want to change the value at bit position 5 and 6 to 01. (Right now it is 10, which is 2 in decimal, and I want to replace it to 1 e 01) without other bits getting affected and write back the register with only bits 5 and 6 modified (so it becomes 126 after changing).
I tried doing this:
reg_data = 0x146
reg_data |= 1 << shift // In this case, 'shift' is 5
If I do this, the value at bit positions 5 and 6 will become 11 (0x3), not 01 (0x1) which I wanted.
How do I go about doing read, modify, and write?
How do I replace only certain bit/bits in a 32/64 bit fields without affecting the whole data of the field using C?
Setting a bit is okay, but more than one bit, I am finding it little difficult.
Use a bitmask. It is sort of like:
new_value = 0, 1, 2 or 3 // (this is the value you will set in)
bit_mask = (3<<5) // (mask of the bits you want to set)
reg_data = (reg_data & (~bit_mask)) | (new_value<<5)
This preserves the old bits and OR's in the new ones.
reg_data &= ~( (1 << shift1) | (1 << shift2) );
reg_data |= ( (1 << shift1) | (1 << shift2) );
The first line clears the two bits at (shift1, shift2) and the second line sets them.
Here is a generic process which acts on a long array, considering it a long bitfield, and addresses each bit position individually:
#define set_bit(arr,x) ((arr[(x)>>3]) |= (0x01 << ((x) & 0x07)))
#define clear_bit(arr,x) (arr[(x)>>3] &= ~(0x01 << ((x) & 0x07)))
#define get_bit(arr,x) (((arr[(x)>>3]) & (0x01 << ((x) & 0x07))) != 0)
It simply takes the index, uses the lower three bits of the index to identify eight different bit positions inside each location of the char array, and the upper remainder bits addresses in which array location does the bit denoted by x occur.
To set a bit, you need to OR the target word with another word with 1 in that specific bit position and 0 in all other with the the target. All 0's in the other positions ensure that the existing 1's in the target are as it is during OR, and the 1 in the specific positions ensures that the target gets the 1 in that position. If we have mask = 0x02 = 00000010 (1 byte) then we can OR this to any word to set that bit position:
target = 1 0 1 1 0 1 0 0
OR + + + + + + + +
mask 0 0 0 0 0 0 1 0
---------------
answer 1 0 1 1 0 1 1 0
To clear a bit, you need to AND the target word with another word with 0 in that specific bit position and 1 in all. All 1's in all other bit positions ensure that during AND the target preserves its 0's and 1's as they were in those locations, and a 0 in the bit position to be cleared would also set that bit position 0 in the target word. If we have the same mask = 0x02, then we can prepare this mask for clearing by ~mask:
mask = 0 0 0 0 0 0 1 0
~mask = 1 1 1 1 1 1 0 1
AND . . . . . . . .
target 1 0 1 1 0 1 1 0
---------------
answer 1 0 1 1 0 1 0 0
Apply a mask against the bitfield to maintain the bits that you do not want to change. This will also clear out the bits that you will be changing.
Ensure that you have a bitfield that contains only the bits that you want to set/clear.
Either use the or operator to "or" the two bitfields, or just simply add them.
For instance, if you wanted to only change bits 2 thru 5 based on input of 0 thru 15.
byte newVal = (byte)value & 0x0F;
newVal = (byte)value << 2;
oldVal = oldVal & 0xC3;
oldVal = oldval + newVal;
The question was about how to implement it in C, but as all searches for "replace bits" lead to here, I will supply my implementation in VB.NET.
It has been unit test tested. For those who are wondering what the ToBinaryString extension looks like: Convert.ToString(value,2)
''' <summary>
''' Replace the bits in the enumValue with the bits in the bits parameter, starting from the position that corresponds to 2 to the power of the position parameter.
''' </summary>
''' <param name="enumValue">The integer value to place the bits in.</param>
''' <param name="bits">The bits to place. It must be smaller or equal to 2 to the power of the position parameter.</param>
'''<param name="length">The number of bits that the bits should replace.</param>
''' <param name="position">The exponent of 2 where the bits must be placed.</param>
''' <returns></returns>
''' <remarks></remarks>'
<Extension>
Public Function PlaceBits(enumValue As Integer, bits As Integer, length As Integer, position As Integer) As Integer
If position > 31 Then
Throw New ArgumentOutOfRangeException(String.Format("The position {0} is out of range for a 32 bit integer.",
position))
End If
Dim positionToPlace = 2 << position
If bits > positionToPlace Then
Throw New ArgumentOutOfRangeException(String.Format("The bits {0} must be smaler than or equal to {1}.",
bits, positionToPlace))
End If
'Create a bitmask (a series of ones for the bits to retain and a series of zeroes for bits to discard).'
Dim mask As Integer = (1 << length) - 1
'Use for debugging.'
'Dim maskAsBinaryString = mask.ToBinaryString'
'Shift the mask to left to the desired position'
Dim leftShift = position - length + 1
mask <<= leftShift
'Use for debugging.'
'Dim shiftedMaskAsBinaryString = mask.ToBinaryString'
'Shift the bits to left to the desired position.'
Dim shiftedBits = bits << leftShift
'Use for debugging.'
'Dim shiftedBitsAsBinaryString = shiftedBits.ToBinaryString'
'First clear (And Not) the bits to replace, then set (Or) them.'
Dim result = (enumValue And Not mask) Or shiftedBits
'Use for debugging.'
'Dim resultAsBinaryString = result.ToBinaryString'
Return result
End Function
You'll need to do that one bit at a time. Use the or, like you're currently doing, to set a bit to one, and use the following to set something to 0:
reg_data &= ~ (1 << shift)
You can use this dynamic logic for any number of bit and in any bit field.
Basically, you have three parts in a bit sequence of number -
MSB_SIDE | CHANGED_PART | LSB_SIDE
The CHANGED_PART can be moved up to the extreme MSB or LSB side.
The steps to replace a number of bit(s) are as follows -
Take only the MSB_SIDE part and replace all the remaining bits with 0.
Update the new bit sequence by adding your desired bit sequence in particular position.
Update the entire bit sequence with LSB_SIDE of the original bit sequence.
org_no = 0x53513C;
upd_no = 0x333;
start_pos = 0x6, bit_len = 0xA;
temp_no = 0x0;
temp_no = org_no & (0xFFFFFFFF << (bit_len + start_pos)); // This is step 1
temp_no |= upd_no << start_pos; // This is step 2
org_no = temp_no | (org_no & ~(0xFFFFFFFF << start_pos)); // This is step 3`
Note: The masking with 0xFFFFFFFF is considered as 32 bit. You can change accordingly with your requirement.

Resources