Reputation: 13
To my understanding, when right-shifting an unsigned integer a number of places in C, the empty positions to the left are filled with zeroes.
However, I have been trying to right-shift ~0 (which would be 1111...1111) without any success at all. Trying to right-shift it any amount of places produces the same value except when I store the integer in a variable prior to the shift:
#include <stdio.h>
int main() {
// Using an expression:
printf("%u \n", ~0);
printf("%u \n", ~0 >> 2);
unsigned int temp = ~0;
// Using a variable to store the value before shift:
printf("%u \n", temp);
printf("%u \n", temp >> 2);
return 0;
}
Output:
4294967295
4294967295
4294967295
1073741823
Left-shifting ~0 is perfectly fine when performed in either manner. I'm not sure what's going on here.
Upvotes: 0
Views: 153
Reputation: 16540
The following proposed code corrects the OPs code and addresses the comments to the question, including the removal of the undefined behavior.
#include <stdio.h>
int main( void )
{
// Using an expression:
printf("%u \n", ~0U);
printf("%u \n", ~0U >> 2);
unsigned int temp = ~0U;
// Using a variable to store the value before shift:
printf("%u \n", temp);
printf("%u \n", temp >> 2);
return 0;
}
the output is:
4294967295
1073741823
4294967295
1073741823
Upvotes: 0
Reputation: 30906
~0U >> 2
This will make sure that it is unsigned. Otherwise you were having signed operation.
Integral literals are always of type int
(signed int
). Now when you were left shifting that it is sign extended.
%u
expects unsigned int. You have passed a signed int to it. This is Undefined behavior.
Upvotes: 3
Reputation: 7433
The type of the expression 0
is int
, not unsigned int
. Therefore, ~0
is the int
with value 0xffffffff
(assuming 32-bit int
s, which it looks like you have). On most systems, this means -1
, and right-shifting a signed integer will sign-extend (keep it negative if it starts negative), giving 0xffffffff
again.
When you print it with %u
, the printf
function reads this signed int
with value -1
as an unsigned int
, and prints what 0xffffffff
means for an unsigned int
.
Note that all of this is just what happens on most systems most of the time. This has multiple instances of undefined or implementation-defined behavior (bit pattern of negative int
s, what right-shifting negative int
s does, and what the %u
format specifier means when you pass in an int
instead of an unsigned int
).
Upvotes: 3