Please explain to me in detail the difference between << and <<= and as well as >> and >>=.
I know how shift operators work, but I am not so sure about them when it comes to >>= or <<=.
Well << only shifts left. <<= shifts left and assigns.
<<= is to << what += is to +.
EDIT
As suggested by MByD, here is an example
int x = 1;
/* Print 32. */
printf("%d\n", x << 5);
/* x stays the same. */
printf("%d\n", x);
x <<= 5;
/* x has become 32. */
printf("%d\n", x);
In C, and many other languages, you can put = after an operator as a shortcut. Instead of writing...
x = x + 5
...I can write...
x += 5
These are called compound assignment operators. You're just seeing the versions of these for bit shift operations.
x >>= 1
...is the same as...
x = x >> 1
<< can be used on both variables and constants.
5 << 2; // this is ok.
a << 2; // this is ok too.
<<= will change the lvalue, so that:
a <<= 2; // bit-shifts a by two positions.
5 <<= 2; // wrong, 5 is 5 and will always be 5.
Related
As part of my coding class, an intro to C, I'm working on a coding project dealing with bit manipulation under restrictions. On this question in particular, I'm stuck because I don't know how to fix my error.
/*
* SigBitMask - return a mask that marks the position of the
* most significant 1 bit. If x == 0, return 0
* Example: SigBitMask(96) = 0x40
* Legal operations: ! ~ & ^ | + << >>
* Max operations: 16
* Rating: 4
*/
Besides the legal operations listed, I can't use any statements such as do, if, while, or else. I'm not allowed cast to other data types either., this includes using unsigned. Also I can't use any constant bigger than 0xFF, which is super important for this problem since I'm not allowed to use 0x80000000. Also, assume we are using a 32 bit machine.
A big thing here is that I can't use operations like - or * which would make this a lot easier.
Here is my code so far:
int SigBitMask(int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x = x ^ (x >> 1);
return x & ~(x >> 1);
}
The error the checking software is giving me says:
"ERROR: Test SigBitMask(-2147483648[0x80000000]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000]
I'm not quiet sure how to go about fixing my problem. I'd prefer more than just the answer. Can someone actually explain the process too. The whole point of this project is to learn to code in C. Thanks :)
Edit: I know there is a similar problem on Stack Overflow already, but their restrictions were different than mine, plus I'm looking for help fixing my code, and understanding why.
Edit2: Clarified what max and legal ops meant
Get rid of your last line because it doesn't do anything. So your function becomes:
int SigBitMask(int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x ^ (x >> 1);
}
This works great for non-negative inputs, but for negative inputs, x will be -1 when the last line runs, so the last line will give a result of zero. But that's bad, because we want to return -2147483648 (i.e. 0x80000000) for all negative inputs.
What if we could patch the return expression, by using | to combine it with another expression that is 0x80000000 when x is -1, and 0 when is x is non-negative? (We don't care about its values for other negative values of x.) Can you think of such an expression? I can think of one using only 3 operators, but it involves a little bit of undefined behavior.
I have probably a newby question about bitwise shifts in C. I wanted to write a macro, which will return a n-th bit of the unsigned char. My initial idea was to left shift by (7-n), bringing the bit to MSB position, and right shift by 7, bringing the bit to LSB. This didnt work, so I started with testing in non-macro enviroment.
So this doesnt work:
int main() {
unsigned char c=126,d,i;
for(i=0;i<8;++i){
d = (c<<(7-i)) >> 7;
printf("%d bit: %d\n",i,d);
}
return 0;
}
But this works:
int main() {
unsigned char c=126,d,i;
for(i=0;i<8;++i){
d = (c<<(7-i));
d >>= 7;
printf("%d bit: %d\n",i,d);
}
return 0;
}
I solved the original problem with &mask.. d=(c>>i)&1;. However, I still dont understand why are those two different... Any ideas?
With unsigned char c=126 and i==0:
(c<<(7-i)) is a 14-bit value.
d = (c<<(7-i)) >> 7; retains that 14-bit value then shifts right 7: information preserved.
d = (c<<(7-i)); d >>= 7; truncates that 14-bit value to 8-bits when saved into d, then shifts right: information lost.
The correct way to get bit number n is val & (1u << n). With a macro this would be:
#define BIT(val, n) ( (val) & (1u << (n)) )
If you want 1 or 0 then just (bool)BIT(0x80, 7); etc.
Though generally, please refrain from inventing macros like this since val & (1u << n) is already the most readable, canonical form.
This u8 = val & (1u << 7); is far superior to u8 = BIT(val,7);.
[Part of a HW question]
Assume 2's complement, 32bit word-length. Only signed int and constants 0 through 0xFF allowed. I've been asked to implement a logical right shift by "n" bits (0 <= n <= 31) using ONLY the operators:
! ~ & ^ | + << >>
I figured I could store and clear the sign bit, perform the shift, and replace the stored sign bit in its new location.
I would like to implement the operation "31 - n" (w/out using the "-" operator) to find the appropriate location for the stored sign bit post shift.
If n were positive, I could use the expression: "31 + (~n + 1)", but I don't believe this will work in the case when n = 0.
Here's what I have so far:
int logicalShift(int x, int n) {
/* Store & clear sign bit, perform shift, and replace stored sign bit
in new location */
int bit = (x >> 31) & 1; // Store most significant bit
x &= ~(1 << 31); // Clear most significant bit
x = x >> n; // Shift by n
x &= ~((~bit) << (31 - n)); // Replace MSbit in new location
return x;
}
Any help and/or hints are appreciated.
[EDIT: Solved]
Thanks to everyone for the help. ~n + 1 works to negate n in this situation, including for the case n = 0 (where it returns 0 as desired). Functional code is below (by no means the most elegant solution). Utility operations borrowed from: How do you set, clear, and toggle a single bit?
int logicalShift(int x, int n) {
/* Store & clear sign bit, perform shift, and replace stored sign bit
in new location */
int bit = (x >> 31) & 1; // Store most significant bit
x &= ~(1 << 31); // Clear most significant bit
x = x >> n; // Shift by n
x ^= ((~bit + 1) ^ x) & (1 << (31 + (~n + 1))); // Replace MSbit in new location
return x;
}
A simple solution is
int logicalShift(int x, int n) {
return (x >> n) ^ (((x & 0x80000000) >> n) << 1);
}
Sadly, using the constant 0x80000000 is forbidden. We could calculate it as 1 << 31 (ignoring undefined behavior in C) or, to save on instruction, calculate 31 - n as n ^ 31 and then use the following somewhat more contrived method:
int logicalShift(int x, int n) {
int b = 1 << (n ^ 31);
return b ^ ((x >> n) + b);
}
I want to find out the number of bit 1 is odd or even.
Here is the code:
int odd_ones(unsigned x)
{
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return !(x&1);
}
But I don't know how it works; I've been stuck at this for long time.
Try to prove that after doing x ^= x >> 16; the last 16 bits of x will have the same parity of 1s as the original value x(assuming x is 32 bit). Then after doing x ^= x >> 8; the last 8 bits of x will have the same parity of 1-s as the last 16 bits of x before the operation. As a rule when you do x ^= x >> L, the last L bits of the result will have the same parity of 1s as the parity of 1s in last 2*L bits of the original value of x.
Following is a circuit diagram of an 8-bit parity generator. Your code tries to implement this combinatorial circuit to a sequential logic (for 32-bits).
Imagining the working of this circuit would help you understand the code.
The equivalent code for above circuit i.e. for 8-bits would be:
int odd_ones(unsigned x)
{
x ^= x >> 1;
x ^= x >> 2;
x ^= x >> 4;
return !(x&1);
}
image courtesy Brigham Young University
I want to create a function that returns the next multiple of 2^p.
Here's an attempt, but not sure if it works...:
#define P 20
#define ALIGN_FORWARD(x, alignment) ((((int)x) + ((alignment)-1)) & (~((alignment)-1)))
int round_up(int x)
{
return ALIGN_FORWARD(x, P);
}
This snippet first fills up all bits below the highest set bit. After v |= v >> 1 the first two bits can be copied and so on. Finally the value is incremented by one.
uint32_t v = ...;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v += 1;
The unsigned part of uint32_t is important, because otherwise the result would be always 0, because the sign bit gets extended by the shift operation. If the value is a uint64_t, then you have to add a further shift, if it is a uint16_t, then you have to remove a shift.
For an input of 8 the result would be 16. You need to test if the input is a power of two if you don't like that. Knowing that the binary representation of a power of two is one character shorter when you decrement it (8=0b1000, 7=0b111), you can use this guard:
if ((v & (v - 1)) > 0) {
…
}
(Reproduced from memory. Original from https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2, which contains many more interesting tricks.)