I am trying to understand a CRC-32 algorithm. Is there an equivalent expression for:
y = (X >> 31) ^ (data >> 7);
using &, something like
y = (x & 0x8000) ^ (data & 0x800)
Well it depends on your calculations but in bit operations each operator has its own motive to do things. Same answer can be obtained by different operations but that doesn't mean that operator to equivalent to each other. Each operator has different motive to achieve.
bit a bit b a & b (a AND b) a | b (a OR b) a ^ b (a XOR b)
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
The purpose of << and >> is to shit bits/drop bits from calculations
Right Shift
The symbol of right shift operator is >>. For its operation, it requires two operands. It shifts each bit in its left operand to the right. The number following the operator decides the number of places the bits are shifted (i.e. the right operand). Thus by doing ch >> 3 all the bits will be shifted to the right by three places and so on.
i = 14; // Bit pattern 1110
j = i >> 1; // bit pattern shifted 1 thus we get 111 = 7 = 14/2
Left shift
The symbol of left shift operator is <<. It shifts each bit in its left-hand operand to the left by the number of positions indicated by the right-hand operand. It works opposite to that of right shift operator. Thus by doing ch << 1 in the above example we have 11001010. Blank spaces generated are filled up by zeroes as above.
Left shift can be used to multiply an integer in multiples of 2 as in:
int i = 4; /* bit pattern equivalent is 100 */
int j = i << 2; /* makes it 10000, original number by 4 i.e. 16 */
Related
Let *c be 32bit in Memory and xmc[] array of 32bit in memory (abstract: Network packet)
xmc[0] = (*c >> 4) & 0x7;
xmc[1] = (*c >> 1) & 0x7;
xmc[2] = (*c++ & 0x1) << 2;
xmc[2] |= (*c >> 6) & 0x3;
xmc[3] = (*c >> 3) & 0x7;
What do the lines xmc[2] of code do to the Value (thought in binary)?
I tried to look up the arithmetic, but I failed understanding the part beginning from *c++.
EDIT: Added more context for clarification
Dereferencing and increment:
First, you are taking the value stored at the address pointed by the c pointer and incrementing the address.
Bitwise AND with a mask: A bitwise AND (&) is done with a mask of value 0x1 (decimal 1), which means that only the least significant bit is taken out of the value stored at the address c.
Think about it like that: You can have a variable on 4 bits, called a, with a decimal value of 3 (binary 0011) and you are doing a bitwise AND between a and a mask of decimal value 2 (binary 10), also on 4 bits (so 0010):
a = 0011
b = 0010
Bitwise AND (a & b or a & (0x10)) will compute an AND between each two bits from a and b. First bit in a is 1, first bit in b is 0 => least significant bit in the result is 1 & 0 = 0, go on with the second bits of each variable, leading to the second least significant bit in the result being 1, and so on...
AND with such a mask is typically used to take a certain bit (or a group of bits) from a value stored in a variable. In your case, your code takes the least significant bit stored in a.
Left shift: The left shift << takes the least significant bit two positions to the left (e.g. from 0001 to 0100), adding 2 bits on 0 to the right.
Let's assume that we operating on a unsigned 32 bit value. Then code
xmc[2] = (*c++ & 0x1) << 2;
is equivalent to
uint32_t tmp1 = *c; // Read the value that c points to and
c = c + 1; // increment the pointer c
// These two lines is the *c++ part
uint32_t tmp2 = tmp1 & 0x1; // Make tmp2 equal to the least significant bit of tmp1
// i.e. tmp2 will be 1 if tmp1 is odd and
// tmp2 will be 0 if tmp1 is even
uint32_t tmp3 = tmp2 << 2; // Make tmp3 equal to tmp2 shifted 2 bits to the left
// This is the same as: tmp3 = tmp2 * 4
xmc[2] = tmp3; // Save the result in xmc[2]
In pseudo code this means:
If the value pointed to be c is odd, set xmc[2] to 4
If the value pointed to be c is even, set xmc[2] to 0
Increment the pointer c
Today's date could be said to be 20230215.
If you have that as a number, you could extract the components as follows:
n = 20230215;
y = n / 10000 % 10000;
m = n / 100 % 100;
d = n / 1 % 100;
The code in question does the same thing. It's extracting four values (a, b, c and d) spread over two bytes.
c[0] c[1]
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
| | a | a | a | b | b | b | c | | c | c | d | d | d | | | |
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
Since we want to extract bits instead of digits, we need to use powers of two instead of using powers of ten. When dealing with powers of two, >> can be used in lieu of division, and & can be used in lieu of %.
To extract a, b, c and d, we could use the following:
n = ( c[0] << 8 ) | c[1];
xmc[0] = ( n >> 12 ) & 0x7;
xmc[1] = ( n >> 9 ) & 0x7;
xmc[2] = ( n >> 6 ) & 0x7;
xmc[3] = ( n >> 3 ) & 0x7;
The posted code takes an approach that avoids calculating n, but it does the same thing.
++ is a post-increment operator in C language, and it would be the last operation before assigning a value to the left of the =.
xmc[2] = (*c++ & 0x1) << 2;
This statement could be considered to:
de-reference : *c
bit-wise AND : *c & 0x1
left-shift : (*c & 0x1) << 2
post-increment : c++
assign to left of = : xmc[2] = the result of the 3rd step.
But, the compiler would optimize these operations by its design and might increase c before the bit-wise AND operation by utilizing the registers of CPU and stacks in the memory. i.e. differences might be found in the final assembly code.
The posted code could be more easily read if it were, equivalently:
xmc[0] = (c[0] >> 4) & 0x7;
xmc[1] = (c[0] >> 1) & 0x7;
xmc[2] = (c[0] & 0x1) << 2;
xmc[2] |= (c[1] >> 6) & 0x3;
xmc[3] = (c[1] >> 3) & 0x7;
(And then, if later code depended on c being advanced, this could be followed by a standalone c++.)
It looks like xmc[0] is taken from three particular bits of c[0], and xmc[1] is taken from three other bits of c[0]. Then the next field straddles a word boundary, in that xmc[2] is composed by putting together one bit from c[0], and two bits from c[1]. Finally xmc[3] is taken from three other bits of c[1].
#ikegami's answer has more of the details.
I'm very new to C and i'm trying to understand bitwise operators in C
I found this code in front of me (to convert 2 to 37)
int main(void)
{
int x = 2;
x = (x<<x<<x) | (x<<x<<x) | (x << !!x) | !!x ;
printf("%d\n" , x ); // prints 37
}
Now it's the first time i see something like this (x<<x<<x) and i don't understand what it is doing.
Can anyone please explain the second line in code in detail?
I'd recommend you to split this long line into few small pieces (sometimes it is more effective to try such things; i.e. reading of the documentation only is not enough):
int x = 2;
printf("%d\n", x); // prints 2
printf("%d\n", x << x); // prints 8
printf("%d\n", x << x << x); // prints 32
printf("%d\n", !!x); // prints 1
printf("%d\n", x << !!x); // prints 4
printf("%d\n", x); // prints 2 (just to become sure that x was not changed)
So, you know that initial long line is equal to x = (32 | 32 | 1 | 4). But this is 32+4+1=37.
Let's see in details:
What is << and >>?
The shift operators bitwise shift the value on their left by the number of bits on their right:
<< shifts left and adds zeros at the right end.
>> shifts right and adds either 0s, if value is an unsigned type, or extends the top bit (to preserve the sign) if its a signed type.
Also the C standard says about E1 >> E2: "If E1 has a signed type and a negative value, the resulting value is implementation-defined." Arithmetic shift is not guaranteed.
Since << is left associative, x<<x<<x is evaluated as (x<<x)<<x.
See also: What are bitwise shift (bit-shift) operators and how do they work?
What is !!x?
It is an unary NOT and an unary NOT.
!!x can be used as shorthand for (x != 0 ? 1 : 0).
This is known as "obfuscation": writing needlessly complex code in order to make something seem more advanced that it is.
Looking at the sub-expression x<<x<<x, it is simple logical left shifts. The operator associativity of shift operators is left-to-right, so the expression is equal to (x<<x)<<x.
We left shift
2 by 2 and get 8. 8 << 2, left shift 8 by 2 and get 32:
x = 32 | 32 | (x << !!x) | !!x ;
Then for any expression with bitwise OR 32 | 32 where the operands 32 are identical, is the very same thing as just writing 32 without the OR. So it is equivalent to:
x = 32 | (x << !!x) | !!x ;
!! is a somewhat common though obscure trick in C to convert any integer to a boolean value 0 or 1. !! is not one operator, but two times the logical not operator !. First we have !2 which is 0. Then !0 which gives 1. We are left with this:
x = 32 | (2 << 1) | 1;
2 << 1 is 4, so:
x = 32 | 4 | 1;
Write it in binary:
0010 0000
OR 0000 0100
OR 0000 0001
------------
0010 0101 = 0x25 hex = 37 dec
I'm someone who writes code just for fun and haven't really delved into it in either an academic or professional setting, so stuff like these bitwise operators really escapes me.
I was reading an article about JavaScript, which apparently supports bitwise operations. I keep seeing this operation mentioned in places, and I've tried reading about to figure out what exactly it is, but I just don't seem to get it at all. So what are they? Clear examples would be great! :D
Just a few more questions - what are some practical applications of bitwise operations? When might you use them?
Since nobody has broached the subject of why these are useful:
I use bitwise operations a lot when working with flags. For example, if you want to pass a series of flags to an operation (say, File.Open(), with Read mode and Write mode both enabled), you could pass them as a single value. This is accomplished by assigning each possible flag it's own bit in a bitset (byte, short, int, or long). For example:
Read: 00000001
Write: 00000010
So if you want to pass read AND write, you would pass (READ | WRITE) which then combines the two into
00000011
Which then can be decrypted on the other end like:
if ((flag & Read) != 0) { //...
which checks
00000011 &
00000001
which returns
00000001
which is not 0, so the flag does specify READ.
You can use XOR to toggle various bits. I've used this when using a flag to specify directional inputs (Up, Down, Left, Right). For example, if a sprite is moving horizontally, and I want it to turn around:
Up: 00000001
Down: 00000010
Left: 00000100
Right: 00001000
Current: 00000100
I simply XOR the current value with (LEFT | RIGHT) which will turn LEFT off and RIGHT on, in this case.
Bit Shifting is useful in several cases.
x << y
is the same as
x * 2y
if you need to quickly multiply by a power of two, but watch out for shifting a 1-bit into the top bit - this makes the number negative unless it's unsigned. It's also useful when dealing with different sizes of data. For example, reading an integer from four bytes:
int val = (A << 24) | (B << 16) | (C << 8) | D;
Assuming that A is the most-significant byte and D the least. It would end up as:
A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011
Colors are often stored this way (with the most significant byte either ignored or used as Alpha):
A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000
To find the values again, just shift the bits to the right until it's at the bottom, then mask off the remaining higher-order bits:
Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF
0xFF is the same as 11111111. So essentially, for Red, you would be doing this:
Color >> 16 = (filled in 00000000 00000000)11111111 00010101 (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)
It is worth noting that the single-bit truth tables listed as other answers work on only one or two input bits at a time. What happens when you use integers, such as:
int x = 5 & 6;
The answer lies in the binary expansion of each input:
5 = 0 0 0 0 0 1 0 1
& 6 = 0 0 0 0 0 1 1 0
---------------------
0 0 0 0 0 1 0 0
Each pair of bits in each column is run through the "AND" function to give the corresponding output bit on the bottom line. So the answer to the above expression is 4. The CPU has done (in this example) 8 separate "AND" operations in parallel, one for each column.
I mention this because I still remember having this "AHA!" moment when I learned about this many years ago.
Bitwise operators are operators that work on a bit at a time.
AND is 1 only if both of its inputs are 1.
OR is 1 if one or more of its inputs are 1.
XOR is 1 only if exactly one of its inputs are 1.
NOT is 1 only if its input are 0.
These can be best described as truth tables. Inputs possibilities are on the top and left, the resultant bit is one of the four (two in the case of NOT since it only has one input) values shown at the intersection of the two inputs.
AND|0 1 OR|0 1
---+---- ---+----
0|0 0 0|0 1
1|0 1 1|1 1
XOR|0 1 NOT|0 1
---+---- ---+---
0|0 1 |1 0
1|1 0
One example is if you only want the lower 4 bits of an integer, you AND it with 15 (binary 1111) so:
203: 1100 1011
AND 15: 0000 1111
------------------
IS 11: 0000 1011
These are the bitwise operators, all supported in JavaScript:
op1 & op2 -- The AND operator compares two bits and generates a result of 1 if both bits are 1; otherwise, it returns 0.
op1 | op2 -- The OR operator compares two bits and generates a result of 1 if the bits are complementary; otherwise, it returns 0.
op1 ^ op2 -- The EXCLUSIVE-OR operator compares two bits and returns 1 if either of the bits are 1 and it gives 0 if both bits are 0 or 1.
~op1 -- The COMPLEMENT operator is used to invert all of the bits of the operand.
op1 << op2 -- The SHIFT LEFT operator moves the bits to the left, discards the far left bit, and assigns the rightmost bit a value of 0. Each move to the left effectively multiplies op1 by 2.
op1 >> op2 -- The SHIFT RIGHT operator moves the bits to the right, discards the far right bit, and assigns the leftmost bit a value of 0. Each move to the right effectively divides op1 in half. The left-most sign bit is preserved.
op1 >>> op2 -- The SHIFT RIGHT - ZERO FILL operator moves the bits to the right, discards the far right bit, and assigns the leftmost bit a value of 0. Each move to the right effectively divides op1 in half. The left-most sign bit is discarded.
In digital computer programming, a bitwise operation operates on one or more bit patterns or binary numerals at the level of their individual bits. It is a fast, primitive action directly supported by the processor, and is used to manipulate values for comparisons and calculations.
operations:
bitwise AND
bitwise OR
bitwise NOT
bitwise XOR
etc
List item
AND|0 1 OR|0 1
---+---- ---+----
0|0 0 0|0 1
1|0 1 1|1 1
XOR|0 1 NOT|0 1
---+---- ---+---
0|0 1 |1 0
1|1 0
Eg.
203: 1100 1011
AND 15: 0000 1111
------------------
= 11: 0000 1011
Uses of bitwise operator
The left-shift and right-shift operators are equivalent to multiplication and division by x * 2y respectively.
Eg.
int main()
{
int x = 19;
printf ("x << 1 = %d\n" , x <<1);
printf ("x >> 1 = %d\n", x >>1);
return 0;
}
// Output: 38 9
The & operator can be used to quickly check if a number is odd or even
Eg.
int main()
{
int x = 19;
(x & 1)? printf("Odd"): printf("Even");
return 0;
}
// Output: Odd
Quick find minimum of x and y without if else statement
Eg.
int min(int x, int y)
{
return y ^ ((x ^ y) & - (x < y))
}
Decimal to binary
conversion
Eg.
#include <stdio.h>
int main ()
{
int n , c , k ;
printf("Enter an integer in decimal number system\n " ) ;
scanf( "%d" , & n );
printf("%d in binary number
system is: \n " , n ) ;
for ( c = 31; c >= 0 ; c -- )
{
k = n >> c ;
if ( k & 1 )
printf("1" ) ;
else
printf("0" ) ;
}
printf(" \n " );
return 0 ;
}
The XOR gate encryption is popular technique, because of its complixblity and reare use by the programmer.
bitwise XOR operator is the most useful operator from technical interview perspective.
bitwise shifting works only with +ve number
Also there is a wide range of use of bitwise logic
To break it down a bit more, it has a lot to do with the binary representation of the value in question.
For example (in decimal):
x = 8
y = 1
would come out to (in binary):
x = 1000
y = 0001
From there, you can do computational operations such as 'and' or 'or'; in this case:
x | y =
1000
0001 |
------
1001
or...9 in decimal
Hope this helps.
When the term "bitwise" is mentioned, it is sometimes clarifying that is is not a "logical" operator.
For example in JavaScript, bitwise operators treat their operands as a sequence of 32 bits (zeros and ones); meanwhile, logical operators are typically used with Boolean (logical) values but can work with non-Boolean types.
Take expr1 && expr2 for example.
Returns expr1 if it can be converted
to false; otherwise, returns expr2.
Thus, when used with Boolean values,
&& returns true if both operands are
true; otherwise, returns false.
a = "Cat" && "Dog" // t && t returns Dog
a = 2 && 4 // t && t returns 4
As others have noted, 2 & 4 is a bitwise AND, so it will return 0.
You can copy the following to test.html or something and test:
<html>
<body>
<script>
alert("\"Cat\" && \"Dog\" = " + ("Cat" && "Dog") + "\n"
+ "2 && 4 = " + (2 && 4) + "\n"
+ "2 & 4 = " + (2 & 4));
</script>
It might help to think of it this way. This is how AND (&) works:
It basically says are both of these numbers ones, so if you have two numbers 5 and 3 they will be converted into binary and the computer will think
5: 00000101
3: 00000011
are both one: 00000001
0 is false, 1 is true
So the AND of 5 and 3 is one. The OR (|) operator does the same thing except only one of the numbers must be one to output 1, not both.
I kept hearing about how slow JavaScript bitwise operators were. I did some tests for my latest blog post and found out they were 40% to 80% faster than the arithmetic alternative in several tests. Perhaps they used to be slow. In modern browsers, I love them.
I have one case in my code that will be faster and easier to read because of this. I'll keep my eyes open for more.
The following two C functions are equivalent:
unsigned f(unsigned A, unsigned B) {
return (A | B) & -(A | B);
}
unsigned g(unsigned A, unsigned B) {
unsigned C = (A - 1) & (B - 1);
return (C + 1) & ~C;
}
My question is: why are they equivalent? What rules/transforms occur to g which transform it into f?
1a. Expression x & -x is a well-known "bit hack": it evaluates to a value that has all bits set to 0 except for one bit: the lowest 1 bit in the original value of x. (Unless x is 0, of course.)
For example, in unsigned arithmetic: 5 & -5 = 1, 4 & -4 = 4 etc.
2a. This immediately tells us what function f does: by using | operator it combines all 1 bits in A and B and then finds the lowest 1 in the combined value. In other words, the result of f is a word that contains a sole 1 bit in the position of the lowest 1 in A or B.
1b. Expression (x + 1) & ~x is a well-known "bit hack": it evaluates to all bits set to 0 except for the lowest 0 bit in the original value of x. The lowest 0 bit in x becomes the sole 1 in the resultant value. (Unless x is all-1-bits, of course.)
For example, in unsigned arithmetic: (5 + 1) & -5 = 2, (4 + 1) & -4 = 1 etc.
2b. Expression x - 1 replaces all trailing 0 bits in x with 1 and replaces the lowest 1 in x with 0, keeping the rest of x unchanged. Operator & combines all 0 bits (just like operator | combines all 1 bits). That means that (A - 1) & (B - 1) will have its lowest 0 bit where the lowest 1 bit was in A or B.
3b. Per 1b, (C + 1) & ~C replaces that lowest 0 with a lone 1, zeroing out everything else.
That means that g does the same thing as f. Both functions find and return the lowest 1 bit between two input values. The result is always a power of 2 (or just 0). E.g. if at least one input value is odd, the result is 1.
I have an intuitive feeling (which could be wrong) that in order to build a formal transformation of one function into the other by applying additional operations to the existing expressions, one needs at least one of these functions to be "reversible" (is some semi-informal meaning of the term). Neither of these two looks sufficiently "reversible" to me...
How would I go about setting up an if statement using only the following bitwise operations:
!
~
&
^
|
+
<<
>>
As an example: "if x is negative then add 15"
This would mean that if the input was x = 0xF0000000, then we would produce 0xF000000F. If the input was x = 0x00000004, we would produce 0x00000004.
You can add 15 to a number if it is negative, and 0 otherwise as follows. Shifting a negative number right will shift in 1's if the value is negative, and 0's otherwise. Shifting by 31 will fill the int with either 1's or 0's. ANDing by 0xF will set the summand to 15 if it is negative, and 0 otherwise, resulting in no change to x.
x += (x >> 31) & 0xF;
If you're worried about the implementation dependent behavior of shifting a signed number to the right. You can do the same thing with the following code, however you still are depending on a two's complement representation of the number. The shift results in 0 or 1, the multiplication scales the number to the appropriate value.
x += (((unsigned)x >> 31) * 0xF);