Doreas
Doreas

Reputation: 13

Right Shifting Unsigned Integers in C Issue: Vacated Bits Not 0 When Shifting ~0?

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

Answers (3)

user3629249
user3629249

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

user2736738
user2736738

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

Daniel H
Daniel H

Reputation: 7433

The type of the expression 0 is int, not unsigned int. Therefore, ~0 is the int with value 0xffffffff (assuming 32-bit ints, 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 ints, what right-shifting negative ints does, and what the %u format specifier means when you pass in an int instead of an unsigned int).

Upvotes: 3

Related Questions