I have a very simple code, in which logical shift works with ~0 value in strange way
As I know its related to the signed/unsigned data types
#include <stdio.h>
void printfbits(int x) {
for (int i=7; i>=0;i--) {
printf("%d", x>>i & 1);
}
printf("\n");
}
int main() {
printfbits(~0>>1);
}
I expect 0111111, not 1111111. I also tried, no success
printfbits(((unsigned int)~0)>>1);
On most platforms, int is 32 bits or 64 bits long. Therefore, you are shifting more than 8 bits to the right, which leaves you with more than 8 bits enabled:
11...11111111 >> 1
becomes:
11...11111111 // if sign extension happens
01...11111111 // if not
As you see, regardless of whether sign extension happens or not, you will still see all 1s since you only print the lower 8 bits.
Right shift of negative signed values is implementation defined. For gcc, a 1 is shifted in, otherwise a 0 is shifted in.
You were on the right track with the cast, but it doesn't help since the function still expects an int. You need to change the function to take an unsigned char and you have to mask out all but the lowest byte before performing the shift in the function call.
#include <stdio.h>
void printfbits(unsigned char x) {
for (int i=7; i>=0;i--) {
printf("%d", x>>i & 1);
}
printf("\n");
}
int main() {
printfbits((~0u & 0xff)>>1);
}
Also, note the use of the U suffix on the constant 0. That gives the constant a type of unsigned int.
The negation in ~0 will happen with type int.
But even if you do ~(unsigned char)0, it'll still happen with type int because of implicit promotions.
Consequently, you'll get extra more 1-bits on the left (int is usually 32 bits large (must be at least 16)).
You can strip them by casting the bitnegation result to uint8_t.
I'd also recommend doing bit ops on unsigneds (0u rather than 0) as the semantics are better standardized for those.
#include <stdio.h>
#include <stdint.h>
void printfbits(int x) {
for (int i=7; i>=0;i--) {
printf("%d", x>>i & 1);
}
printf("\n");
}
int main() {
printfbits( (uint8_t)~0u >>1 ); //prints 01111111
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With