Combine Set, Clear and Toggle in one line of C - c

I am trying to combine three bit operations in one line of C. For a 8 bit char, I have to set bits 2, 4, 6; clear bits 1, 3, 7 and toggle bit 0 and 5 all in one line code of C. I could do these in three line but I cannot combine these. Below is what I have done so far:
x= x & 0xD5;
x = x | 0x51;
x = x ^ 0x84;
They give the right answer for a given value of x. But I tried
x = (x & 0xD5) | (x | 0x51) | (x ^ 0x84)
And
x = x & 0xD5 | 0x51 ^ 0x84
Those do not work. Any suggestion would be appreciated.

It's simply this
x = (((x & 0xD5) | 0x51) ^ 0x84)
Your first try is wrong, because the values of x are not updated so all the operations work on the same value, besides oring the values is not equivalent to assigning the result of the operation to x.
The second, is wrong because or operator precedence, so you just need parentheses.

Your second solution fails because of operator precedence. You can fix it this way:
x = ((x & 0xD5) | 0x51) ^ 0x84;
But there is a more efficient solution:
x = (x & (0xD5 & ~0x51)) ^ (0x84 | 0x51);
You clear the bits you want to clear and the bits you want to set and then toggle both the bits you want to toggle and the bits you want to set. It compiles to one less operation because the constant operations are folded at compile time.

Related

Why must I use the ~ operator when clearing a bit? [duplicate]

This question already has answers here:
How do I set, clear, and toggle a single bit?
(27 answers)
Closed 5 years ago.
For example, if I want to set a bit in y at position n (in C)
y = y | (1 << n)
But if I want to delete a bit in y at position n I have to use the ~ operator after binary AND.
y = y & ~(1 << n);
My question: Why Must I use the ~ operator?
Is this because the result turns into negative area?
If you want to set a bit at third place from the right :
Y : 01001000
1 << 2 : 00000100
Y | (1 << 2) : 01001100 The | is OR, bits are set to 1 if any is 1.
If you want to remove the bit :
1 << 2 : 00000100
~(1 << 2) : 11111011 The ~ is NOT, bits are inversed
Y : 01001100
Y & ~(1 << 2) : 01001000 The & is AND, bits are set to 1 if both are 1.
I suggest you read more about Bitwise operators
No, ~ has nothing to do with interpreting the number as negative: tilde ~ operator interprets the number as a pattern of bits, which it then inverts (i.e. replaces zeros with ones and ones with zeros). In fact, if you apply ~ to an unsigned value, the result would remain positive.
Recall that 1 << k expression produces a pattern of all zeros and a single 1 at the position designated by k. This is a bit mask that can be used to force bit at position k to 1 by applying OR operation.
Now consider what happens when you apply ~ to it: all 0s would become 1s, and the only 1 would become zero. Hence, the result is a bit mask suitable for forcing a single bit to zero by applying AND operation.
The ~ operator turns all of the 0's to 1's and all of the 1's to 0's. In order to clear the bint in position n you want to and it will all ones and a zero in the nth position so shift a one to the nth position and ~ invert all the bits.
1 << n for n==3 (just an example) gives you a pattern 0000000...0001000. ~ negates the bit
pattern to 11111111....11110111. Using the bitwise AND operator (&) will
only set the required bit to 0, all other remain with the same value. It's using
the fact that for a bit b: b & 1 == b.
~ flips all bits, it has nothing to do with negative numbers.
A graphical representation for a sequence of k-bits
pos k-1 k-2 0
+---+---+-------------------+---+---+
1: | 0 | 0 | ··· | 0 | 1 |
+---+---+-------------------+---+---+
pos k-1 k-2 n n-1 0
+---+---+-----+---+---+---+-----+---+
1<<n | 0 | 0 | ··· | 1 | 0 | 0 | ··· | 0 |
+---+---+-----+---+---+---+-----+---+
pos k-1 k-2 n n-1 0
+---+---+-----+---+---+---+-----+---+
~(1<<n) | 1 | 1 | ··· | 0 | 1 | 1 | ··· | 1 |
+---+---+-----+---+---+---+-----+---+

How can I interpret << and | in C

I need help to understand what is happening in this declaration:
#define LDA(m) (LDA_OP << 5 | ((m) & 0x001f))
Thank you
y << x is a left shift of y by x.
x & y is a bitwise and of x and y.
So, the left shift operator is like multiplying by 10 in base 10, but instead you multiply for 2 in base 2, for example:
In base 10
300 * 10 = 3000
In base 2:
0b0001 * 2 = 0b0010 = 0b0001 << 1
with a << b you "push" the number a, b places to the left.
and the or operator ( | )
you have to take two bits and if one or both of them are true (1) then the result is true.
For example:
0b0010 | 0b0001 = 0b0011
0b0010 | 0b0010 = 0b0010
If you have problems with this operators, just try to work the same numbers but in binary.

C Bit Operation Logic (bitAnd)

Background:
I stumbled across bitwise operators in C here, and now I am trying to learn more about them. I searched around for exercises and came across this.
However, I'm having trouble understanding the first one "bitAnd."
The code reads:
/*
* bitAnd - x&y using only ~ and |
* Example: bitAnd(6, 5) = 4
* Legal ops: ~ |
* Max ops: 8
* Rating: 1
*/
int bitAnd(int x, int y) {
/* NOR Equivelent of AND */
return ~(~x | ~y);
}
Question:
Now, I thought that the pipe ( | ) means "or." So, why do we need ~x and ~y? Can't we just say something like:
int bitAnd(int x, int y) {
int or = x | y; //something is one number or the other
int and = ~or; // not or is the same as and
return and;
}
I wrote and ran the second code sample for myself (I have a main function to run it). I get -8 as the answer, but with values 6 and 5, you should get 4.
If you have something for "or" (the pipe operator) and "and" is just the opposite or, why do we need to use "~" on each value before we calculate ~and?
Some extra information/thoughts:
I understand that "~" flips all the bits in the value. "Or" copies the bit from either value into the other if it exists (I learned that from here). So, if I have:
6 = 00000110
and
5 = 00000101
I should get 0000111.
I only mention that to show what knowledge I have of some of the operations in case my understanding of those are wrong as well.
This is typical logic gates knowledge. The equivalent of an AND gate is NOT of a NOR b.
Let's see what happens. Suppose you have values as such:
a = 00111 => 3
b = 01001 => 9
a AND b = 00001 => 1
This is what we expect. Let's run it through your shared method, the first one:
~a = 11000 => 24
~b = 10110 => 22
~a | ~b = 11110 => 30
~(~a | ~b) = 00001 => 1 as we expect.
Now, let's run your second proposed method.
or = 01111 => 15
and = ~or = 10000 => 16.
Now you have a problem. Logically, what you do is this:
~(a | b) = ~a AND ~b.
Is it really true though?
~a = 11000 => 24
~b = 10110 => 22
~a AND ~b = 10000 => 16.
It agrees with what I said above, however, it's wrong as you can see. We want 1, not 16. The bitwise inverse "~" operator is distributive. It inverts the operations as well. So an "or" becomes an "and" and an "and" becomes an "or". I hope that clears it up.
The solution you provided uses the de Morgan's rules, which say that not (A and B) = not A or not B. Since you need to compute A and B, you negate everything once more and you get: A and B = not (not (A and B)) = not (not A or not B).
Now, you can also think in terms of truth tables to see why this is true and why your claim isn't. I won't show everything in detail, but in your solution, not (A of B) when both A and B are 0, the result is 1, which is not consistent with the and operation.

Understanding this symbol in C

What does the & mean in this code:
(number >> 9) & 0b111
I know about & in terms of pointers. But not sure how it works in the code above
Lets break it down:
(number >> 9) & 0b111
| | | | |
| | | | Binary '7'*
| | | Binary AND
| | Number to shift by
| Binary shift operator
Variable
We'll start with the expression in the parenthesis:
(number >> 9)
This performs a binary right-shift by 9 places. For example:
1101101010010011 will be shifted to become:
0000000001101101
The & symbol is Binary AND. Where the bits are both 1 in both of the source variables, the returned value will have those bits set:
01101
& 11010
= 01000
So your code shifts your number by 9 places and performs AND on the result against b111. As the three least significant bits are all set in the second input, the result of this operation will be the bits that are set in the bottom three bits of the shifted input.
Example:
number = 1101101010010011
number >> 9 = 0000000001101101
(number >> 9) & '111' = 0000000000000101
An alternate way of thinking about it is as follows: The line extracts bits 10-12 and returns them as the result.
XXXXbbbXXXXXXXXX -> bbb
A common use for this is to apply a mask to a value to extract the bits. E.g. some libraries allow you to pass parameters with enumerable types like this:
set_params(option_a | option_b);
which sets both option_a and option_b.
Whether a parameter is set can be read by:
set_params(unsigned int params)
{
if (params & option_a)
{ /* do option_a stuff */}
}
*assuming your compiler has a binary extension to the C spec. otherwise you could use 0x7 (hex 7) or just 7
It is the bitwise AND operator.
More info here:
Wikipedia link
& is Bitwise AND
The C operators are here:
https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

Implementing logical negation with only bitwise operators (except !)

~ & ^ | + << >> are the only operations I can use
Before I continue, this is a homework question, I've been stuck on this for a really long time.
My original approach: I thought that !x could be done with two's complement and doing something with it's additive inverse. I know that an xor is probably in here but I'm really at a loss how to approach this.
For the record: I also cannot use conditionals, loops, ==, etc, only the functions (bitwise) I mentioned above.
For example:
!0 = 1
!1 = 0
!anything besides 0 = 0
Assuming a 32 bit unsigned int:
(((x>>1) | (x&1)) + ~0U) >> 31
should do the trick
Assuming x is signed, need to return 0 for any number not zero, and 1 for zero.
A right shift on a signed integer usually is an arithmetical shift in most implementations (e.g. the sign bit is copied over). Therefore right shift x by 31 and its negation by 31. One of those two will be a negative number and so right shifted by 31 will be 0xFFFFFFFF (of course if x = 0 then the right shift will produce 0x0 which is what you want). You don't know if x or its negation is the negative number so just 'or' them together and you will get what you want. Next add 1 and your good.
implementation:
int bang(int x) {
return ((x >> 31) | ((~x + 1) >> 31)) + 1;
}
The following code copies any 1 bit to all positions. This maps all non-zeroes to 0xFFFFFFFF == -1, while leaving 0 at 0. Then it adds 1, mapping -1 to 0 and 0 to 1.
x = x | x << 1 | x >> 1
x = x | x << 2 | x >> 2
x = x | x << 4 | x >> 4
x = x | x << 8 | x >> 8
x = x | x << 16 | x >> 16
x = x + 1
For 32 bit signed integer x
// Set the bottom bit if any bit set.
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x ^= 1; // Toggle the bottom bit - now 0 if any bit set.
x &= 1; // Clear the unwanted bits to leave 0 or 1.
Assuming e.g. an 8-bit unsigned type:
~(((x >> 0) & 1)
| ((x >> 1) & 1)
| ((x >> 2) & 1)
...
| ((x >> 7) & 1)) & 1
You can just do ~x & 1 because it yields 1 for 0 and 0 for everything else

Resources