Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
I saw lately a thread on this site about using logical operators on integers in C. However, I didn't really understand how this worked so here I provide two examples and I hope someone can provide a detailed explanation for them:
int result = 1000 & 255
int result = 1000 || 255
Decimal 1000 is binary 11 1110 1000. Decimal 255 is binary 1111 1111. First, they are converted to signed int, which is usually 32 bits wide.
Taking & of them sets the bit at all positions where both bits of the operands are set:
0000 0000 0000 0000 0000 0011 1110 1000
0000 0000 0000 0000 0000 0000 1111 1111
& ---------------------------------------
0000 0000 0000 0000 0000 0000 1110 1000
This is decimal 232. Taking | would have set the bit at all positions where at least one bit is set, i.e. would have produced binary 11 1111 1111, which is decimal 1023. Taking ^ would have set the bit at all positions where exactly one of the bits is set, i.e.
0000 0000 0000 0000 0000 0011 1110 1000
0000 0000 0000 0000 0000 0000 1111 1111
^ ---------------------------------------
0000 0000 0000 0000 0000 0011 0001 0111
&& is not a binary operation. It simply returns 1 if and only if both operands are non-zero. || returns 1 if and only if at least one of the operands is non-zero. In other cases, they return 0, respectively.
Related
I am playing around with bit masking and I had thought I understood bitwise math...apparently not.
#include <stdio.h>
int main()
{
printf("%08x", 0x01111111 & 0xF0F0F0F);
/*
* 0000 0001 0001 0001 0001 0001 0001 0001
* 1111 0000 1111 0000 1111 0000 1111
* -----------------------------
* 0000 0000 0001 0000 0001 0000 0001
*/
return 0;
}
Above is a code snippet of a simple bit mask using F0F0F0F to turn off every other byte.
I know that 0111 1111 converted to binary is 0000 0001 0001 0001 0001 0001 0001 0001. If we AND mask this against 1111 0000 1111 0000 1111 0000 1111 I would expected the output to be 0000 0000 0001 0000 0001 0000 0001. However running this program gives a result I didn't expect - 01010101. It would appear the leading 0 in the MSB position is disregarded?
I'm sorry if this is trivial, I'm sure it is. But I am confused by this as I am not sure how this result is given.
0xF0F0F0F is really 0x0F0F0F0F. When you don't type "enough" digits to fill the whole integer, zeros are inserted automatically (e.g. if you just type 0x1, the internal representation is 0x00000001 for 32 bit integers).
So for your code it's
/*
* 0000 0001 0001 0001 0001 0001 0001 0001 (binary)
* 0000 1111 0000 1111 0000 1111 0000 1111 (binary)
* ---------------------------------------
* 0000 0001 0000 0001 0000 0001 0000 0001 (binary)
*/
and when printed as hex, you get 01010101
This is what's happening:
/*
* 0000 0001 0001 0001 0001 0001 0001 0001
* 0000 1111 0000 1111 0000 1111 0000 1111
* -----------------------------
* 0000 0001 0000 0001 0000 0001 0000 0001
*/
0xF0F0F0F has 0's at the beginning. That's what 0x means. So for, 0x1, 1 is the least significant bit.
I have two unsigned ints X and Y, and I want to efficiently decide if X is at most half as long as Y, where the length of X is k+1, where 2^k is the largest power of 2 that is no larger than X.
i.e., X=0000 0101 has length 3, Y=0111 0000 is more than twice as long as X.
Obviously we can check by looking at individual bits in X and Y, for example by shifting right and counting in a loop, but is there an efficient, bit-twiddling (and loop-less) solution?
The (toy) motivation comes from the fact that I want to divide the range RAND_MAX either into range buckets or RAND_MAX/range buckets, plus some remainder, and I prefer use the larger number of buckets. If range is (approximately) at most the square root of RAND_MAX (i.e., at most half as long), than I prefer using RAND_MAX/range buckets, and otherwise I want to use range buckets.
It should be noted, therefore, that X and Y might be large, where possibly Y=1111 1111, in the 8-bit example above. We certainly don't want to square X.
Edit, post-answer: The answer below mentions the built-in count leading zeros function (__builtin_clz()), and that is probably the fastest way to compute the answer. If for some reason this is unavailable, the lengths of X and Y can be obtained through some well-known bit twiddling.
First, smear the bits of X to the right (filling X with 1s except its leading 0s), and then do a population count. Both of these operations involve O(log k) operations, where k is the number of bits that X occupies in memory (my examples are for uint32_t, 32 bit unsigned integers). There are various implementations, but I put the ones that are easiest to understand below:
//smear
x = x | x>>1;
x = x | x>>2;
x = x | x>>4;
x = x | x>>8;
x = x | x>>16;
//population count
x = ( x & 0x55555555 ) + ( (x >> 1 ) & 0x55555555 );
x = ( x & 0x33333333 ) + ( (x >> 2 ) & 0x33333333 );
x = ( x & 0x0F0F0F0F ) + ( (x >> 4 ) & 0x0F0F0F0F );
x = ( x & 0x00FF00FF ) + ( (x >> 8 ) & 0x00FF00FF );
x = ( x & 0x0000FFFF ) + ( (x >> 16) & 0x0000FFFF );
The idea behind the population count is to divide and conquer. For example with
01 11, I first count the 1-bits in 01: there is 1 1-bit on the right, and
there are 0 1-bits on the left, so I record that as 01 (in place). Similarly,
11 becomes 10, so the updated bit-string is 01 10, and now I will add the
numbers in buckets of size 2, and replace the pair of them with the result;
1+2=3, so the bit string becomes 0011, and we are done. The original
bit-string is replaced with the population count.
There are faster ways to do the pop count given in Hacker's Delight, but this
one is easier to explain, and seems to be the basis for most of the others. You
can get my code as a
Gist here..
X=0000 0000 0111 1111 1000 1010 0010 0100
Set every bit that is 1 place to the right of a 1
0000 0000 0111 1111 1100 1111 0011 0110
Set every bit that is 2 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Set every bit that is 4 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Set every bit that is 8 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Set every bit that is 16 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Accumulate pop counts of bit buckets size 2
0000 0000 0110 1010 1010 1010 1010 1010
Accumulate pop counts of bit buckets size 4
0000 0000 0011 0100 0100 0100 0100 0100
Accumulate pop counts of bit buckets size 8
0000 0000 0000 0111 0000 1000 0000 1000
Accumulate pop counts of bit buckets size 16
0000 0000 0000 0111 0000 0000 0001 0000
Accumulate pop counts of bit buckets size 32
0000 0000 0000 0000 0000 0000 0001 0111
The length of 8358436 is 23 bits
Y=0000 0000 0000 0000 0011 0000 1010 1111
Set every bit that is 1 place to the right of a 1
0000 0000 0000 0000 0011 1000 1111 1111
Set every bit that is 2 places to the right of a 1
0000 0000 0000 0000 0011 1110 1111 1111
Set every bit that is 4 places to the right of a 1
0000 0000 0000 0000 0011 1111 1111 1111
Set every bit that is 8 places to the right of a 1
0000 0000 0000 0000 0011 1111 1111 1111
Set every bit that is 16 places to the right of a 1
0000 0000 0000 0000 0011 1111 1111 1111
Accumulate pop counts of bit buckets size 2
0000 0000 0000 0000 0010 1010 1010 1010
Accumulate pop counts of bit buckets size 4
0000 0000 0000 0000 0010 0100 0100 0100
Accumulate pop counts of bit buckets size 8
0000 0000 0000 0000 0000 0110 0000 1000
Accumulate pop counts of bit buckets size 16
0000 0000 0000 0000 0000 0000 0000 1110
Accumulate pop counts of bit buckets size 32
0000 0000 0000 0000 0000 0000 0000 1110
The length of 12463 is 14 bits
So now I know that 12463 is significantly larger than the square root of
8358436, without taking square roots, or casting to floats, or dividing or
multiplying.
See also
Stackoverflow
and Haacker's Delight (it's
a book, of course, but I linked to some snippets on their website).
If you are dealing with unsigned int and sizeof(unsigned long long) >= sizeof(unsigned int), you can just use the square method after casting:
(unsigned long long)X * (unsigned long long)X <= (unsigned long long)Y
If not, you can still use the square method if X is less than the square root of UINT_MAX+1, which you may need to hard code in the function.
Otherwise, you could use floating point calculation:
sqrt((double)Y) >= (double)X
On modern CPUs, this would be quite fast anyway.
If you are OK with gcc extensions, you can use __builtin_clz() to compute the length of X and Y:
int length_of_X = X ? sizeof(X) * CHAR_BIT - __builtin_clz(X) : 0;
int length_of_Y = Y ? sizeof(Y) * CHAR_BIT - __builtin_clz(Y) : 0;
return length_of_X * 2 <= length_of_Y;
__buitin_clz() compiles to a single instruction on modern Intel CPUs.
Here is a discussion on more portable ways to count leading zeroes you could use to implement your length function: Counting leading zeros in a 32 bit unsigned integer with best algorithm in C programming or this one: Implementation of __builtin_clz
I do not see why 3 & 0x1111 = 1 ? It seems that:
for any unsigned 32-bit integer i, i & 0x1111 should be i, right?
However when I tried this on ubuntu 14.04, I got 3 & 0x1111=1. Why?
int main() {
unsigned int a =3;
printf("size of a= %lu\n",sizeof(a));
printf("value of 3 & 0x1111= %d\n",a & 0x1111);
return 0;
}
Convert both of them to binary:
0x1111 = 0001 0001 0001 0001
3 = 0000 0000 0000 0011
When you & them bit by bit, what else do you expect?
In C, any numeric literal starting with 0x is a hexadecimal number. So the bitmask you are using is 1111 in hexadecimal. In the mask, bits #0, #4, #8 and #12 are 1s, and the rest are 0s. That's why you're getting 1.
0x1111 = 0000 0000 0000 0000 0001 0001 0001 0001 in binary
3 = 0000 0000 0000 0000 0000 0000 0000 0011 in binary
------------------------------------------------
1 = 0000 0000 0000 0000 0000 0000 0000 0001 after doing biwise AND
If you want to construct a mask with all 1s, in hex, it should be
0xffffffff = 1111 1111 1111 1111 1111 1111 1111 1111
3d = 3h = 11b
1111h = 0001000100010001b
so:
0001000100010001b
& 11b
-------------------
1b
0x1111 is 0001000100010001 in binary. So 0x1111 & 3 is 0001000100010001 & 0000000000000011 = 0000000000000001
0x1111 is 4369, or as binary: 0001000100010001
So, 3 (0011) masked against that is going to be 0001.
Similarly, 19 (0001011) would be 17 (00010001)
The & operator applies the binary and. The 0x means hexadecimal not binary so if we write 0x1111 into a binary we will get:
0001 0001 0001 0001 binary.
3 binary is 011
and
0001 0001 0001 0001 &
0000 0000 0000 0011 =
0000 0000 0000 0001 = 1
I need help understanding the C language. I just started out.
I have this piece of code from wikipedia:
unsigned int rotl(unsigned int value, int shift) {
return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
}
I do understand what rotation of bits means. I just don't understand this implementation.
Why do I have to perform the OR operator here? And what does the right part actually do?
I shift value to the right for the number of bytes of value times (the number of bits in a char variable minus the shift I want). Why do I have to do this?
If I think of an example.
I want to shift unsigned 1011 (Base 2) 2 Bits to the left.
I do what the code says:
0000 0000 0000 0000 0000 0000 0000 1011 << 2 = 0000 0000 0000 0000 0000 0000 0010 1100
1011 >> (4*(8-2))=24 = 0000 0000 0000 0000 0000 0000 0000 0000 0000;
perform |: = 0000 0000 0000 0000 0000 0000 0010 1100.
Ok that did not work. What am I doing wrong?
Thanks!
Here is a graphical definition of an 8-bit 'Shift Left', and 'Rotate Left':
"Why do I have to perform the OR operator here?"
"And what does the right part actually do?"
For a 'rotate left' operation, the bits that "fall off" the left side are recycled, as they are 'OR'ed back into the right side.
I have a function I'm trying to write of the following form (and haven't found exactly what I'm looking for — if this is a dup please just point me at the right place — even if it's not ints and shorts but, say, chars and ints instead, that would be fine):
put_bits(short *array_of_short, int significant_bits, int bit_offset, int integer_to_append)
Where I overwrite the the significant_bits of integer_to_append at bit_offset in array_of_short.
I'd like to accomplish things by just overwriting (or bitwise oring, or overlaying, or replacing) bits to the position in the array (I don't want to add more elements to the array or allocate more memory) — i.e. it should be easily possible, but pretty inefficient, to just keep track of how many elements into the array the offset translates to, whether this falls on a boundary of the shorts and shift the bits of the integer to the appropriate offset and or them onto the appropriate short(s) — but that seems like loads of overhead and calculating more than I need to vs just oring the bits into the appropriate spot, but I'm kind of at a loss...
So, for example, I have an integer which will contain an arbitrary number of "significant" bits — let's say for this example there are 6. So the values would be from 0 to 63
0000 0000 0000 0000 0000 0000 0000 0000
to
0000 0000 0000 0000 0000 0000 0011 1111
and I want to overlay (or bitwise or this) this to an arbitrarily sized array of short at an arbitrary point. So if I had
Integer:
0000 0000 0000 0000 0000 0000 0010 0001
Array of short:
0100 1000 0100 1100 : 1100 0010 0110 0000 : 0000 0000 0000 0000 : 0000 0000 0000 0000
and I wanted to append at position 42 to get:
0100 1000 0100 1100 : 1100 0010 0110 0000 : 0000 0000 0000 1000 : 0100 0000 0000 0000
If I'm totally off or I don't make sense, let me know too.
If i understand your question correctly, you actually want to treat your array as array of bits. There is no such structure in c as bit array of course, but you can implement it. Here is example of bit array with int as base type. You can adopt this solution with short as base type, and then just set bit by bit something like that:
for( i = 0 ; i< sizeof(int)*8;++i)
{
unsigned int flag = 1;
flag = flag << i;
if( int_num & flag)
SetBit( array_of_short, bit_offset + i );
}
void SetBit( short array_of_short[ ], int k )
{
array_of_short[k/16] |= 1 << (k%16); // Set the bit at the k-th position in array_of_short[i]
}