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...
Related
If x was to equal 12 in a 32 bit scenario, x = multiple 0's into the lsb 0000 1100. If the above scenario were to run, I believe I would get 0000 1100. Am I wrong?
Along with that, what if I was to use x=-1? Wouldn't s = 1, but then does (s & ~x) look like (0001 & 0000) and (1110 & 1111)? Thanks
I thought that x=-1 would mean x>>31 would be like 0001 (output 1), but I don't know if the above is correct.
The typical implementation of a right shift of a signed integer is an arithmetic shift. Different implementations are unfortunately still allowed, though rare, and they're not relevant to understanding this code (it ignores such possibilities anyway). Two's complement integers are now mandatory (in C23: "The sign representation defined in this document is called two’s complement. Previous revisions of this document
additionally allowed other sign representation") so I'm not going to do the usual consideration of hypothetical integer representations that haven't been seen since the stone age.
By assumption the number of bits in an int is 32, so shifting an int right by 31 makes every bit of the result a copy of the sign bit. So if x was negative, s would be -1.
x = (s & ~x) | (~s & x) is a verbose way to spell out x ^= s. XORing x by 0 leaves it the same as before, XORing it by -1 inverts all the bits. Taking into account that s = x < 0 ? -1 : 0, effectively the computation does this:
if (x < 0)
x = ~x; // equivalent to: x = -x - 1;
Given an integer and either 1 or 0, I'd like to be able to get either the integer or 0 using only bitwise operators. That means no if statements, conditionals, etc. Basically integer * i. Two's complement system!
I have been working for a while and it is tricky. Here are my failed attempts:
Edit: ints are unsigned
unsigned int x = 24; // To change
unsigned int i = 0; // identity
((~i) | x) // if i = 0, ~i returns 111...1 || (111...1 | x) = 111...1
// else ~i returns 000...1 || (000...1 | x) = x (+1 sometimes)
The code I have above makes it so if i is 1, then I get the identity (only sometimes), and if i is 0, then I get -1. I'd like it so if i is 1, I get the identity, and if i is 0, I get 0. Thanks!
I think this is what you want:
i & -x
If x is zero, you get i & 0 which is zero. If x is one, you get i & UINT_MAX which is i.
This can be done using
~i + 1u & x
~0u produces UINT_MAX (all bits 1):
1111...1111
Adding 1 goes back to 0:
0000...0000
On the other hand, ~1u produces UINT_MAX - 1:
1111...1110
Adding 1 then gives UINT_MAX (all bits 1):
1111...1111
These are perfect bit masks to use with &: (0 & x) == 0 and (UINT_MAX & x) == x.
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 */
i'm sorry for title for being not spesific but i dont know how it's called. here is my question: in this code snippet, there is constants defined like this:
#define WS_NONE 0
#define WS_RECURSIVE (1 << 0)
#define WS_DEFAULT WS_RECURSIVE
#define WS_FOLLOWLINK (1 << 1) /* follow symlinks */
#define WS_DOTFILES (1 << 2) /* per unix convention, .file is hidden */
#define WS_MATCHDIRS (1 << 3) /* if pattern is used on dir names too */
and there is a function defined like this:
int walk_recur(char *dname, regex_t *reg, int spec)
he sends constants(WS_DEFAULT and WS_MATCHDIRS) to function using "|":
walk_dir(".", ".\\.c$", WS_DEFAULT|WS_MATCHDIRS);
this is how he uses the arguments:
if ((spec & WS_RECURSIVE))
walk_recur(fn, reg, spec);
if (!(spec & WS_MATCHDIRS)) continue;
if WS_RECURSIVE passed to function, first if statement will be true. i didn't get how << operator works and how (spec & WS_RECURSIVE) statement returning true. and how can he sends different constants with "|"? and he can use "spec" value, which must be equal to passed constants, how is that possible?
and sorry for my bad english.
It's a very common idiom for treating a single integer value as a collection of individual bits. C doesn't have direct support for bit arrays, so we use bitwise operators to set and clear the bits.
The << operator is a left-shift operator. For example:
1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
1 << n for any non-negative n (within range) is a power of 2. Each bit in an an integer value represents a power of 2. Any integer value can be treated as a unique sums of powers of 2.
| is the bitwise or operator; it's use to combine multiple 1-bit values (powers of 1) into an integer value:
(1 << 0) | (1 << 3) == 1 | 8
1 | 8 == 9
Here we combine bit zero (representing the value 1) and bit three (representing the value 8) into a single value 9. (We could have used + rather than | in this case, but in general using | avoids problems when some power of 2 is given more than once.)
Now we can test whether a bit is set using the bitwise and operator &:
int n = (1<<0) | (1<<3);
if (n & (1<<3)) {
printf("Bit 3 is set\n");
}
else {
printf("Bit 3 is not set\n");
}
Now we can define macros so we don't have to write 1<<0 and 1<<3 all over the place:
#define WS_RECURSIVE (1 << 0)
...
#define WS_MATCHDIRS (1 << 3)
int n = WS_RECURSIVE | WS_MATCHDIRS;
// n == 9
if (n & WS_RECURSIVE) {
// the WS_RECURSIVE bit is set
}
if (!(n&WS_MATCHDIRS) {
// the WS_MATCHDIRS bit is *not* set
}
You could also define macros to simplify setting and testing bits (SET_BIT(), IS_SET(), etc.), but most C programmers don't bother to do so. Symbolic names for the bit values are important for code readability, but once you understand how the bitwise operators work, and more importantly how the common idioms for setting, clearing, and testing bits are written, the raw operators are readable enough.
It's usually better to use unsigned rather than signed integer types; the behavior of the bitwise operators on signed types can be tricky in some cases.
The << operator is a bitwise left shift.
For example, 1 << 0 translates to 1 'left shifted by' 0 bits. This is effectively a nop as 1 left shifted by 0 bits is still the value 1.
To further clarify, let's look at a bitwise representation of a number (lets say the number is a 16 bit value to illustrate)
1 -> 0b'0000000000000001
1 << 1 would be
2 -> 0b'0000000000000010
And so on.
The | operator is a bitwise or, so the WS_DEFAULT | WS_MATCHDIRS is translated to:
0b'0001 | 0b'1000
This yields the value 0b'1001 which is then passed to the walk_dir.
If you pass in WS_RECURSIVE instead, you will be doing a bitwise and (&) operation using two identical values. This will always result in a true value.
AND Truth Table
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
I've been going through the K&R C Programming Language book and I'm stuck on Exercise 2-6 which reads:
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.
I'm having trouble understanding the exact thing they're looking for me to do. I looked at a possible answer here, but I still don't really understand. I think it's the wording that's throwing me off. Can anyone maybe explain what they're looking for me to do in a different way? I'm hoping that different wording will help me understand what I need to do code wise.
Expounding on Avi's answer:
int i = setbits(0xAB = b10101011, 5, 3, 0xAA = b10101010);
i equals 0x93 = b10010011
Say your i = 0xAB. In binary, this is: 10101011
Let's number each of the bit positions.
Position #: 7 6 5 4 3 2 1 0
Bit: 1 0 1 0 1 0 1 1
The right-most bit (the least-significant) is position "0". The left-most (most-significant) is position "7".
So the next two values, p and n, are saying "You want to modify n bits starting at bit p." So if p=5 and n=3, you want to start at bit number 5, and in total you're modifying 3 bits. Which means bits 5, 4, 3. "101" in this example.
Position #: 7 6 5 4 3 2 1 0
Bit: 1 0 1 0 1 0 1 1
| |
---------
(Modifying these three bits)
How are we modifying them? We are replacing them. With another set of 3 bits. The three least-significant bits from y.
So here's y:
Position #: 7 6 5 4 3 2 1 0
Bit: 1 0 1 0 1 0 1 0
And the right-most bits would be bits 2, 1, 0. or the value "010". Of course, if the value of n=6, then you'd want to replace those six bits from i with "101010" - the rightmost 6 bits.
So your task is to take the specified bits from i - in this case, "101" - and replace them with the specified bits in y - "010".
If you do this, then your return value is
1 0 1 0 1 0 1 0
For example:
int i = setbits(0xAB = b10101011, 5, 3, 0xAA = b10101010);
i equals 0x93 = b10010011
We take the 3 bits beginning at position 5 in x (101), and replace them with the rightmost three bits from y (010).
That "possible answer" is just code without comments. No wonder it didn't help you.
The question (and probably the answerers) assume that you are familiar with bit fields. This sort of thing is very common in embedded programming where you control hardware registers.
Say there's a register that sets the audio volume level, among other things. It might, at the same time, let you select speakers or microphones and things like that. The bits might look like this:
ssAAAmxx -- Each letter represents a bitfield within that number. To change the volume, you have to alter the value of "AAA". Now, lets say you have something in your program that lets you adjust the volume. It's a simple control, and it always returns a number between 0 and 7. The format for that looks like this:
xxxxxAAA -- You job then, is to take the AAA bits from this (call it "y"), and set them into that number above (call it "x"), without altering the bits that aren't the A's. Thus, the problem would read, "Take the rightmost 3 bits of y, and set them into x, starting with bit 5 (remember, they count bits from zero). Then, 3 and 5 in our example become n and p in the original problem.
The operation is "bitfield insert"
The idea is that y would usually be fewer than n bits, but in case it's not, only use n. In english, the task is to insert y into x beginning at p, using a field width of n.
Replace n bits of x, starting at p position, with the rightmost n bits of y.
And probably you should take advantage of the getbits() routine in chapter 2.9
How about this?
unsigned int
setbits(unsigned int x, int p, int n, unsigned int y)
{
char buffer[65];
unsigned x1 = x >> (p + 1);
x1 <<= (p + 1);
/*
* x1 now contains all the bits before position 'p'.
*/
unsigned x2 = y & ~(~0 << n);
x2 <<= (p + 1) - n;
/*
* x2 now contains the rightmost 'n' bits of 'y', left shifted (p + 1) - n bits.
*/
unsigned x3 = x & ~(~0 << ((p + 1) - n));
/*
* x3 now contains the rightmost (p + 1) - n bits.
*/
return x1 | x2 | x3;
}