what is the meaning of k-=(k & (-k)) in c? [duplicate] - c

This question already has answers here:
Why the bit operation i & (-i) equals to rightmost bit?
(3 answers)
Closed 4 years ago.
A function to calculate sum where I encountered with this statement ..plz help
int get_sum(int x) {
int p = 0, k;
for (k = x; k > 0; k -= k & -k)
p += bit[k];
return p;
}

This expression:
k -= (k & (-k))
Is a tricky way of taking the least significant bit that is set in a positive number and clearing that bit. It is dependent on two's compliment representation of negative numbers.
The first part, k & (-k) isolates the least significant bit that is set. For example:
1 & -1:
00000001
& 11111111
--------
00000001
2 & -2:
00000010
& 11111110
--------
00000010
24 & -24:
00011000
& 11101000
--------
00001000
When this value is subtracted from the orignal k, it clears that bit as a result.
So as the loop progresses, the value of k is reduced 1 bit at a time, starting with the lowest. So if for example x was 52, k would be 52, then 48 (52 - 4), then 32 (48 - 16), and would exit at 0 (32 - 32).
As to why the program is doing this, that depends entirely on the definition of bit and what it stores.

Related

C - Using bit-shift operators for base conversion

I'm trying to convert some data from hex to base64 in C, I found an algorithm online but I would really like to know how it works rather than just implenting it and firing it off. If someone could please explain how the following is working I would appreciate it. I have been reading about the shift operators and I don't seem to understand them as much as I thought I did...it's not quite clicking for me.
for (x = 0; x < dataLength; x += 3)
{
/* these three 8-bit (ASCII) characters become one 24-bit number */
n = data[x] << 16;
if((x+1) < dataLength)
n += data[x+1] << 8;
if((x+2) < dataLength)
n += data[x+2];
/* this 24-bit number gets separated into four 6-bit numbers */
n0 = (uint8_t)(n >> 18) & 63;
n1 = (uint8_t)(n >> 12) & 63;
n2 = (uint8_t)(n >> 6) & 63;
n3 = (uint8_t)n & 63;
This code was taken from Wikibooks, it is NOT mine, I'm just trying to understand the bitshifting and how it's allowing me to convert the data.
Thank you for your help, I really appreciate it.
Source: Base64
First of all, the input data is not hex as you say. It's simply data stored as bytes. The code will give you the base64 representation of it (although the code you posted lacks the part which will map n0, n1, n2, n3 to printable ASCII characters).
Suppose the first three bytes of the input are (in binary representation, each letter represents a 0 or 1):
abcdefgh, ijklmnop, qrstuvwx
The first part of the code will combine them to a single 24-bit number. This is done by shifting the first one 16 bits to the left and the second one 8 bits to the left and adding:
abcdefgh0000000000000000 (abcdefgh << 16)
+ 00000000ijklmnop00000000 (ijklmnop << 8)
0000000000000000qrstuvwx
------------------------
abcdefghijklmnopqrstuvwx
Then it separates this into four 6-bit numbers by shifting and and'ing. For example, the second number is calculated by shifting 12 bits to the right and and'ing with 111111
n = abcdefghijklmnopqrstuvwx
n>>12 = 000000000000abcdefghijkl
63 = 000000000000000000111111
And'ing gives:
000000000000000000ghijkl
Ok here is a bit of explanation..
data[x] is an array of chars, a char is usuall 8bits.. (random 8bits number 01010101)
n is a 32bit number here is a random 32bit number(01011111000011110000111100001111)think there are 32bits there :)
remember n is 32bits and data is only 8bits.. lets go through the first line
n = data[x] << 16;
<<16 has precedence over the equal sign so its evaluated first.
data[x] << 16 means move the bits in memory that data[x] represents by 16bits to the left.
suppose data[x] = 'a' this is represented by 01100001 in memory(1 bytes), so lets move is 16bits to the left
n = 00000000 01100001 00000000 00000000
next we have
if((x+1) < dataLength)
n += data[x+1] << 8;
this says move the next char data[x+1] 8 bits and add it to n; so lets move it 8 bits first
( I assumed it was 'a' again)
00000000 00000000 01100001 00000000
(this is done in some register in your processor)
now lets add it to n
00000000 01100001 01100001 00000000
next part is
if((x+2) < dataLength)
n += data[x+2];
lets do the same thing here, notice there is no bit shifting, since the last 8bits of n are free!! all we need to do is add it to n
b = 01100010 (assumed data[x+2] = 'b')
adding it to n
00000000 01100001 01100001 01100010
great so now we have a 24bits number(actually n is 32bits but the last 24bits is what we need)
next part
n0 = (uint8_t)(n >> 18) & 63;
(take note n0 is only 8bits wide or a single unsigned byte)
take n and move it to the left by 18bits and "and" it with 63
n = 00000000 01100001 01100001 01100010
n moved 18bits to right is 00000000 00000000 00000000 00011000
now n is cast to an unsigned int of 8bits (uint8_t)
so now it becomes 00011000
last part is the & operator(bitwise and)
00011000 &
00111111
n0= 00011000
now repeat this for the rest

int val=0xCAFE Test if at least three of last four bits (LSB) are on

I'm trying to learn C on my own. I came across this exercise and i am studying to understand it. I have read about masking bits and in order to get the last four bits we should do val&0xF.I have read this post as well What is Bit Masking?. The part that i need an explanation is why the possible values are 0x7,0xB,0xD,0xE,0xF. I am studying the answer and i have read various articles. If someone is willing to explain to me this part i would appreciate it.
Because these are all the possible numbers with at least three of the last four bits on. If you write down every binary number from 0 to 15, you will see that these have at least three of the last four bits set:
0111 (0x7)
1011 (0xB)
1101 (0xD)
1110 (0xE)
1111 (0xF)
Think of it like this: every binary number from 0 to 6 has at most 2 bits set:
0 (0)
1 (1)
10 (2)
11 (3)
100 (4)
101 (5)
110 (6)
Thus, none of it matches the rule. From 7 up to 15, we have:
111 (7)
1000 (8)
1001 (9)
1010 (10)
1011 (11)
1100 (12)
1101 (13)
1110 (14)
1111 (15)
From these, only 7, 11, 13, 14 and 15 have three of the last four bits set.
This method is easy to implement:
int chk_last_bits2(unsigned x) {
return ((x & 0x7) == 0x7) ||
((x & 0xB) == 0xB) ||
((x & 0xD) == 0xD) ||
((x & 0xE) == 0xE) ||
((x & 0xF) == 0xF);
}
Note that we have to explicitly test for equality for each case. For example, x & 0xB will return a non-zero value for every number with any of 1011 bits set. This is not what we want, we want all of them to be on, which can be tested with equality.
Another possible solution would be:
int chk_last_bits(unsigned x) {
int i, j;
for (i = 1, j = 0; i < 32; i <<= 1)
if (i & x)
j++;
return j >= 3;
}
Since you're learning C, I'll leave this one for you to try to understand.
Masking means filtering bits and keeping only some of them, which are of interest, as you will have understood.
Let's say that you have a variable something and a mask, both are unsigned values: something & mask will return a value whose bits are 0 where the mask is 0 and the value they had in something where the mask is 1. This is the and mask.
To understand why you use those particular values, you have to recall how bitwise operations (&, |...) work in C. When you write a & b, then the corresponding bits of the two variables are orderly combined using the specified logical operator. For instance, if a is 10001010 and b is 00000011, then a & b is 00000010 (orderly, 1 and 0, 0 and 0, 0 and 0, 0 and 0, 1 and 0, 0 and 0, 1 and 1, 0 and 1).
If you understood that, then you can understand what those masks will select. Consider their binary representation:
0x7 --> ...00000111 --> the three LSBs
0xb --> ...00001011 --> the first, second and fourth LSBs
0xd --> ...00001101 --> the first, third and fourth LSBs
0xe --> ...00001110 --> the second, third and fourth LSBs
0xf --> ...00001111 --> the 4 LSBs
This was for and masking, which is for extracting values (refer to the answer you linked). xor and or masking would work similarly, just recall how the logical function behaves.
#include <stdio.h>
int main()
{
/*
32 Bit binary: 00000000000000001100101011111110
Decimal: 51966
*/
int val = 0xCAFE;
/*
Note:
First it does loop, after that it shifts the bits of `i`,
so `i` is 1 at the beginning.
When shifting operator appears always think of bits.
Step 1
Decimal: i = 1
32 Bit binary: 00000000000000000000000000000001
Step 2
Decimal: 1 << 1 = 2
32 Bit binary: 00000000000000000000000000000010
Step 3
Decimal: 2 << 1 = 4
32 Bit binary: 00000000000000000000000000000100
... and so on ... 1, 2, 4, 8, 16, 32, stop.
This indicates 2^n.
----------------------------------------------------------------
Inside the for loop we run the AND operator to find out
which bits are `on` and which are `off`.
AND only works if both are true.
Step 1:
Last bit
00000000000000000000000000000001
AND 00000000000000001100101011111110
---------------------------------
00000000000000000000000000000000
Decimal: 1
Second last bit
Step 2:
00000000000000000000000000000010
AND 00000000000000001100101011111110
---------------------------------
00000000000000000000000000000010
Decimal: 2
... and so on ...
As we can see we gradually check for last 4 bits until
we reach the 4th loop 2^4 = 32 and the loop stops.
*/
int i;
for (i = 1; i < 32; i = i << 1) {
/*
You can simply add a counter over here
and return the value at the end.
*/
printf("%d\n", i & val);
}
}

bit manipulation: clearing range of bits

I'm preparing for an interview using the text, "Cracking the Coding Interview" by Gayle Laakman McDowell. On the section covering bit manipulation, there are two functions that are provided, but I don't quite understand how it works.
// To clear all bits from the most significant bit through i (inclusive), we do:
int clearMSBthroughI(int num, int i) {
int mask = (1 << i) - 1;
return num & mask;
}
// To clear all bits from i through 0 (inclusive), we do:
int clearBitsIthrough0(int num, int i) {
int mask = ~(((1 << (i+1)) - 1);
return num & mask;
}
In the first function, I understand what (1 << i) does of course, but what I'm not sure of is how subtracting 1 from this value affects the bits (i.e., (1 << i) - 1)).
I basically have the same confusion with the second function. To what effects, specifically on the bits, does subtracting 1 from ((1 << (i+1)) have? From my understanding, ((1 << (i+1)) results in a single "on" bit, shifted to the left i+1 times--what does subtracting this by 1 do?
Thanks and I hope this was clear! Please let me know if there are any other questions.
For those who by some chance have the text I'm referencing, it's on page 91 in the 5th Edition.
let's assume i= 5
(1 << i) give you 0100000 the 1 is placed in the 6th bit position
so now if we substract 1 from it, then we get 0011111 ==> only the 5 first bit are set to 1 and others are set to 0 and that's how we get our mask
Conclusion: for a giving i the (1 << i) -1 will give you a mask with the i first bits set to 1 and others set to 0
For the first question:
lets say i = 5
(1 << i ) = 0010 0000 = 32 in base 10
(1 << i ) -1 = 0001 1111 = 31
So a & with this mask clears the most significant bit down to i because all bit positions above and including index i will be 0 and any bellow will be 1.
For the second question:
Again lets say i = 5
(1 << (i + 1)) = 0100 0000 = 64 in base 10
(1 << (i + 1)) - 1 = 0011 1111 = 63
~((1 << (i + 1)) - 1) = 1100 0000 = 192
So a & with this masks clears bits up to index i
First Function:
Let's take i=3 for example. (1 << i) would yield 1000 in binary. Subtracting 1 from that gives you 0111 in binary (which is i number of 1's). ANDing that with the number will clear all but the last i bits, just like the function description says.
Second Function:
For the second function, the same applies. If i=3, then ((i << (i+1)) - 1) gives us 01111. The tilde inverts the bits, so we have 10000. It's important to do it this way instead of just shifting i bits left, because there could be any number of significant bits before our mask (so 10000 could be 8 bits long, and look like 11110000. That's what the tilde gets us, just to be clear). Then, the number is ANDed with the mask for the final result
// To clear all bits from the most significant bit through i (inclusive), we do:
int clearMSBthroughI(int num, int i) {
int mask = (1 << i) - 1;
return num & mask;
}
Take the example of i = 3
1<<3 gives you 0x00001000
(1<<3)-1 gives you 0x00000111
num & (1<<i)-1 will clear the bits from msb to i
// To clear all bits from i through 0 (inclusive), we do:
int clearBitsIthrough0(int num, int i) {
int mask = ~(((1 << (i+1)) - 1);
return num & mask;
}
same example of i = 3 gives you
1 <<(3+1) =0x00010000
1 <<(3+1)-1 = 0x00001111
mask =~(1<<(3+1)-1) = 0x11110000
num & mask will cleaR the bits from 0 throuh i

Setting invidual bits in byte by group of bits

For example:
We have a byte A: XXXX XXXX
We have a byte B: 0000 0110
And now for example we want 4 bits from byte B on specific position and we want to put inside byte A on specific position like so we have a result:
We have a byte A: 0110 XXXX
Im still searching through magic functions without success.
Found similar and reworking it but still have no endgame with it:
unsigned int i, j; // positions of bit sequences to swap
unsigned int n; // number of consecutive bits in each sequence
unsigned int b; // bits to swap reside in b
unsigned int r; // bit-swapped result goes here
unsigned int x = ((b >> i) ^ (b >> j)) & ((1U << n) - 1); // XOR temporary
r = b ^ ((x << i) | (x << j));
As an example of swapping ranges of bits suppose we have have b = 00101111 (expressed in binary) and we want to swap the n = 3 consecutive bits starting at i = 1 (the second bit from the right) with the 3 consecutive bits starting at j = 5; the result would be r = 11100011 (binary).
This method of swapping is similar to the general purpose XOR swap trick, but intended for operating on individual bits. The variable x stores the result of XORing the pairs of bit values we want to swap, and then the bits are set to the result of themselves XORed with x. Of course, the result is undefined if the sequences overlap.
It's hard to understand your requirenments exactly, so correct me if I'm wrong:
You want to take the last 4 bits of a byte (B) and add them to the first for bits of byte A? You use the term 'put inside' but it's unclear what you mean exactly by it (If not adding, do you mean replace?).
So assuming addition is what you want you could do something like this:
A = A | (B <<4)
This will shift by 4 bits to the left (thereby ending up with 01100000) and then 'adding ' it to A (using or).
byte A: YYYY XXXX
byte B: 0000 0110
and you want 0110 XXXX
so AND A with 00001111 then copy the last 4 bits of B (first shift then OR)
a &= 0x0F; //now a is XXXX
a |= (b << 4); //shift B to 01100000 then OR to get your result
if you wanted 0110 YYYY just shift a by 4 to the right instead of AND
a >>= 4
Found an solution :
x = ((b>>i)^(r>>j)) & ((1U << n) -1)
r = r^(x << j)
where r is the 2nd BYTE, i,j are indexes in order (from,to).

how to find left most 1 in a 32bit int in C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Find the highest order bit in C
How can I write a C function that will generate a mask indicating the leftmost 1 in x.
Ex: 0xFF00 -> 0x8000, and 0x6600 -> 0x4000. So far:
int left1(unsigned x){}
I understand, 0xFF00 == 1111 1111 0000 0000..
and 0x6600 == 0110 0110 0000 0000.. but I'm stumped after that.
You can do this in two parts: first, use a technique called "bit smearing" to ensure that all the bits to the right of the first 1 are also 1:
x |= x >> 16;
x |= x >> 8;
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
At this point, an input of 0xFF00 will leave x equal to 0xFFFF, and an input of 0x6600 will leave x equal to 0x7FFF. We can then leave just the highest 1 set using:
x ^= x >> 1;
Count the number of times it takes to bit-shift to the right until you reach 1, then bit-shift that 1 to the left by that same count.
int ct=0;
while (x > 1) { ct++; x = x >> 1; }
x = x << ct;
One approach is to create a bitmask, and then right-shift the value.
That is, create a bitmask so that your integer is '1000....' or '0.....' - depending on whether that first bit is a 0 or a 1.
Then take that integer and right-shift it until it becomes the least-significant-bit, rather than the most-significant. As an example, 0b10000000 >> 8 is 1.
So first, depending on the size of your integer, you have to shift, well, however many bits are relevant.
Then you have to create the bitmask. Let's just take a 1-byte integer:
unsigned int i = 1 << 8 would create an integer i whose most significant bit is a 1.
Or you could use hex. You already know that 0xFF == 11111111. You can actually break it up further: 0xF0 == 11110000
Since 0xF == 1111 in binary, well, we will do the reverse. 1000 in binary is what, in hex? 1000 in binary is the number 8, which also happens to equal 0x8
So, for a single byte, the mask for the leftmost bit is 0x80.
Now! Apply this to 32 bits!
Good luck!

Resources