Why does -1 >> 1 and 0xFFFFFFFF >> 1 produce different results?

bit-shift, bitwise-operators, c

Solution

It is not an assumption. What type do you think `0xffffffff` is ? According to the C standard, 6.4.4.1 Integer constants, the type of the expression of a hexadecimal constant (preceded with `0x`) is the first of the following which can applicably hold the represented value:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

On your platform, 0xFFFFFFFF cannot be represented as `int` because `int` is 32 bits and only 31 bits express quantity in `signed int` (the standard dictates one bit is reserved for sign). The next type, `unsigned int`, is therefore used. Therefore no sign bit is present to extended with the shift operation, which is thereby logical rather than arithmetic.

It may not be apparent how I concluded `int` was 32 bits on your platform. Indeed I could not make that assumption were it not for the first line, which arithmetic-right-shifts the value of `-1`. The result of that shift, dumped as `%x`, was `0xFFFFFFFF`. Had `int` been native 64-bits that should dump `0xFFFFFFFFFFFFFFFF` instead. Without that prior knowledge, no single type conclusion of `0xFFFFFFFF` could be assumed since it may well be representable as a standard signed `int` of width 64-bits (63+1) with value `0x00000000FFFFFFFF`. The resulting shift would produce the same output you see now, thereby introducing an alternative to that postulated above.

Problem

I am trying to make a test to tell whether my PC performs arithmetic or logical right shift by right-shifting hexadecimal `FFFFFFFF` by `1`. I know that an integer `-1` reads as `FFFFFFFF` in hexadecimal since it is the two's complement of `1`. Right-shifting `-1` by `1` results in `FFFFFFFF` and shows the PC performed arithmetic right shift. But if I just type in `0xFFFFFFFF >> 1`, it resulted in `7FFFFFFF` and shows that the PC performed logical right shift instead. Why did that happen? See for the code below that produced the results: ``` #include <stdlib.h> #include <stdio.h> int main ( int argc, char *argv[] ) { printf ( "%x >> 1 = %x\n", -1, -1 >> 1 ); printf ( "%x >> 1 = %x\n", 0xffffffff, 0xffffffff >> 1 ); return EXIT_SUCCESS; } ``` The program's output was: ``` ffffffff >> 1 = ffffffff ffffffff >> 1 = 7fffffff ```

Original source