How are the individual bits accessed in this code? - c

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.

Related

is bitwise AND operator transitive in C and C++?

I have a question: Is bitwise anding transitive, particularly in C and C++?
Say res=(1 & 2 & 3 & 4), is this same as res1=(1&2) and res2=(3&4) and
res= (res1 & res2). Will this be same?
Yes, bitwise AND is transitive as you've used the term.
It's perhaps easier to think of things as a stack of bits. So if we have four 4-bit numbers, we can do something like this:
A = 0xB;
B = 0x3;
C = 0x1;
D = 0xf;
If we simply stack them up:
A 1 0 1 1
B 0 0 1 1
C 0 0 0 1
D 1 1 1 1
Then the result of a bitwise AND looks at one column at a time, and produces a 1 for that column if and only if there's a 1 for every line in that column, so in the case above, we get: 0 0 0 1, because the last column is the only one that's all ones.
If we split that in half to get:
A 1 0 1 1
B 0 0 1 1
A&B 0 0 1 1
And:
C 0 0 0 1
D 1 1 1 1
C&D 0 0 0 1
Then and those intermediate results:
A&B 0 0 1 1
C&D 0 0 0 1
End 0 0 0 1
Our result is still going to be the same--anywhere there's a zero in a column, that'll produce a zero in the intermediate result, which will produce a zero in the final result.
The term you're looking for is associative. We generally wouldn't call a binary operator "transitive". And yes, & and | are both associative, by default. Obviously, you could overload the operators to be something nonsensical, but the default implementations will be associative. To see this, consider one-bit values a, b, and c and note that
(a & b) & c == a & (b & c)
because both will be 1 if and only if all three inputs are 1. And this is the operation that is being applied pointwise to each bit in your integer values. The same is true of |, simply replacing 1 with 0.
There are also some issues to consider if your integers are signed, as the behavior is dependent on the underlying bit representation.

K&R C programming language exercise 2-9

I don't understand the exercise 2-9, in K&R C programming language,
chapter 2, 2.10:
Exercise 2-9. In a two's complement number system, x &= (x-1) deletes the rightmost 1-bit in x . Explain why. Use this observation to write a faster version of bitcount .
the bitcount function is:
/* bitcount: count 1 bits in x */
int bitcount(unsigned x)
{
int b;
for (b = 0; x != 0; x >>= 1)
if (x & 01)
b++;
return b;
}
The function deletes the rightmost bit after checking if it is bit-1 and then pops in the last bit .
I can't understand why x&(x-1) deletes the right most 1-bit?
For example, suppose x is 1010 and x-1 is 1001 in binary, and x&(x-1) would be 1011, so the rightmost bit would be there and would be one, where am I wrong?
Also, the exercise mentioned two's complement, does it have something to do with this question?
Thanks a lot!!!
First, you need to believe that K&R are correct.
Second, you may have some mis-understanding on the words.
Let me clarify it again for you. The rightmost 1-bit does not mean the right most bit, but the right most bit which is 1 in the binary form.
Let's arbitrary assume that x is xxxxxxx1000(x can be 0 or 1). Then from right to left, the fourth bit is the "rightmost 1-bit". On the basis of this understanding, let's continue on the problem.
Why x &=(x-1) can delete the rightmost 1-bit?
In a two's complement number system, -1 is represented with all 1 bit-pattern.
So x-1 is actually x+(-1), which is xxxxxxx1000+11111111111. Here comes the tricky point.
before the righmost 1-bit, all 0 becomes 1 and the rightmost 1-bit becomes 0 and there is a carry 1 go to left side. And this 1 will continue to proceed to the left most and cause an overflow, meanwhile, all 'x' bit is still a because 'x'+'1'+'1'(carry) causes a 'x' bit.
Then x & (x-1) will delete the rightmost 1-bit.
Hope you can understand it now.
Thanks.
Here is a simple way to explain it. Let's arbitrarily assume that number Y is xxxxxxx1000 (x can be 0 or 1).
xxxxxxx1000 - 1 = xxxxxxx0111
xxxxxxx1000 & xxxxxxx0111 = xxxxxxx0000 (See, the "rightmost 1" is gone.)
So the number of repetitions of Y &= (Y-1) before Y becomes 0 will be the total number of 1's in Y.
Why do x & (x-1) delete the right most order bit? Just try and see:
If the righmost order bit is 1, x has a binary representation of a...b1 and x-1 is a...b0 so the bitwise and will give a...b1 because common bits are left unchanged by the and and 1 & 0 is 0
Else x has a binary representation of a...b10...0; x-1 is a...b01...1 and for same reason as above x & (x-1) will be a...b00...0 again clearing the rightmost order bit.
So instead of scanning all bits to find which one are 0 and which one are 1, you just iterate the operation x = x & (x-1) until x is 0: the number of steps will be the number of 1 bits. It is more efficient than the naive implementation because statistically you will use half number of steps.
Example of code:
int bitcount(unsigned int x) {
int nb = 0;
while (x != 0) {
x &= x-1;
nb++
}
return nb;
}
Ik I'm already very late (≈ 3.5yrs) but your example has mistake.
x = 1010 = 10
x - 1 = 1001 = 9
1010 & 1001 = 1000
So as you can see, it deleted the rightmost bit in 10.
7 = 111
6 = 110
5 = 101
4 = 100
3 = 011
2 = 010
1 = 001
0 = 000
Observe that the position of rightmost 1 in any number, the bit at that same position of that number minus one is 0. Thus ANDing x with x-1 will be reset (i.e. set to 0) the rightmost bit.
7 & 6 = 111 & 110 = 110 = 6
6 & 5 = 110 & 101 = 100 = 4
5 & 4 = 101 & 100 = 100 = 4
4 & 3 = 010 & 011 = 010 = 2
3 & 2 = 011 & 010 = 010 = 2
2 & 1 = 010 & 001 = 000 = 0
1 & 0 = 001 & 000 = 000 = 0

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;

k&r exercise confusion with bit-operations

The exercise is:
Write a function setbits(x,p,n,y) that returns x with the n bits that begin at position p set to the rightmost n bits of y, leaving the other bits unchanged.
My attempt at a solution is:
#include <stdio.h>
unsigned setbits(unsigned, int, int, unsigned);
int main(void)
{
printf("%u\n", setbits(256, 4, 2, 255));
return 0;
}
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
return (x >> (p + 1 - n)) | (1 << (n & y));
}
It's probably incorrect, but am I on the right path here? If not, what am I doing wrong? I'm unsure as to why I don't perfectly understand this, but I spent about an hour trying to come up with this.
Thanks.
Here's your algorithm:
If n is 0, return x.
Take 1, and left shift it n times and then subtract 1. Call this mask.
Left shift mask p times call this mask2.
And x with the inverse of mask2. And y with mask, and left shift p times.
Or the results of those two operations, and return that value.
I think the answer is a slightly modified application of the getbits example from section 2.9.
Lets break it down as follows:
Let bitstring x be 1 0 1 1 0 0
Let bitstring y be 1 0 1 1 1 1
positions -------->5 4 3 2 1 0
Setting p = 4 and n =3 gives us the bitstring from x which is 0 1 1. It starts at 4 and ends at 2 and spans 3 elements.
What we want to do is to replace 0 1 1 with 1 1 1(the last three elements of bitstring y).
Lets forget about left-shift/right-shift for the moment and visualize the problem as follows:
We need to grab the last three digits from bitstring y which is 1 1 1
Place 1 1 1 directly under positions 4 3 and 2 of bitstring x.
Replace 0 1 1 with 1 1 1 while keeping the rest of the bits intact...
Now lets go into a little more detail...
My first statement was:
We need to grab the last three digits from bitstring y which is 1 1 1
The way to isolate bits from a bitstring is to first start with bitstring that has all 0s.
We end up with 0 0 0 0 0 0.
0s have this incredible property where bitwise '&'ing it with another number gives us all 0s and bitwise '|'ing it with another number gives us back that other number.
0 by itself is of no use here...but it tells us that if we '|' the last three digits of y with a '0', we will end up with 1 1 1. The other bits in y don't really concern us here, so we need to figure out a way to zero out those numbers while keeping the last three digits intact. In essence we need the number 0 0 0 1 1 1.
So lets look at the series of transformations required:
Start with -> 0 0 0 0 0 0
apply ~0 -> 1 1 1 1 1 1
lshift by 3 -> 1 1 1 0 0 0
apply ~ -> 0 0 0 1 1 1
& with y -> 0 0 0 1 1 1 & 1 0 1 1 1 1 -> 0 0 0 1 1 1
And this way we have the last three digits to be used for setting purposes...
My second statement was:
Place 1 1 1 directly under positions 4 3 and 2 of bitstring x.
A hint for doing this can be found from the getbits example in section 2.9. What we know about positions 4,3 and 2, can be found from the values p = 4 and n =3. p is the position and n is the length of the bitset. Turns out p+1-n gives us the offset of the bitset from the rightmost bit. In this particular example p+1-n = 4 +1-3 = 2.
So..if we do a left shift by 2 on the string 0 0 0 1 1 1, we end up with 0 1 1 1 0 0. If you put this string under x, you will notice that 1 1 1 aligns with positions 4 3 and 2 of x.
I think I am finally getting somewhere...the last statement I made was..
Replace 0 1 1 with 1 1 1 while keeping the rest of the bits intact...
Lets review our strings now:
x -> 1 0 1 1 0 0
isolated y -> 0 1 1 1 0 0
Doing a bitwise or on these two values gives us what we need for this case:
1 1 1 1 0 0
But this would fail if instead of 1 1 1, we had 1 0 1...so if we need to dig a little more to get to our "silver-bullet"...
Lets look at the above two strings one more time...
x -> bit by bit...1(stays) 0(changes) 1(changes) 1(changes) 0(stays) 0(stays)
So ideally..we need the bitstring 1 x x x 0 0, where the x's will be swapped with 1's.
Here's a leap of intuition that will help us..
Bitwise complement of isolated y -> 1 0 0 0 1 1
& this with x gives us -> 1 0 0 0 0 0
| this with isolated y -> 1 1 1 1 0 0 (TADA!)
Hope this long post helps people with rationalizing and solving such bitmasking problems...
Thanks
Note that ~0 << i gives you a number with the least significant i bits set to 0, and the rest of the bits set to 1. Similarly, ~(~0 << i) gives you a number with the least significant i bits set to 1, and the rest to 0.
Now, to solve your problem:
First, you want a number that has all the bits except the n bits that begin at position p set to the bits of x. For this, you need a mask that comprises of 1 in all the places except the n bits beginning at position p:
this mask has the topmost (most significant) bits set, starting with the bit at position p+1.
this mask also has the least significant p+1-n bits set.
Once you have the above mask, & of this mask with x will give you the number you wanted in step 1.
Now, you want a number that has the least significant n bits of y set, shifted left p+1-n bits.
You can easily make a mask that has only the least significant n bits set, and & it with y to extract y's least significant n bits.
Then, you can shift this number by p+1-n bits.
Finally, you can bitwise-or (|) the results of step 2 and 3.2 to get your number.
Clear as mud? :-)
(The above method should be independent of the size of the numbers, which I think is important.)
Edit: looking at your effort: n & y doesn't do anything with n bits. For example, if n is 8, you want the last 8 bits of y, but n & y will just pick the 4th bit of y (8 in binary is 1000). So you know that can't be right. Similarly, right-shifting x p+1-n times gives you a number that has the most significant p+1-n bits set to zero and the rest of the bits are made of the most significant bits of x. This isn't what you want either.

Resources