# Why is an int variable valued `0xffffffff` >> 1 != 0x7fffffff?

3
``````  int c = 0xffffffff;
printf("%x\n", (c) == (0xffffffff));
printf("%x\n", (c >> 1) == (0xffffffff >> 1));
``````

The first output is `1` but the second output is `0`. And `c >> 1` outputs `0xffffffff`. But why?

c

## 2 Answers

8

The integer constant `0xffffffff` has the type `unsigned int`. So when you perform a right shift on this value, bits with value 0 are shifted in from the left.

In contrast, `c` is an `int` and contains a negative value. Performing a right shift on a negative value is implementation-defined, although most implementations will preserve the sign by shifting in bits with value 1 from the left.

As to why this prints 1 when comparing a positive and a negative value:

``````printf("%x\n", (c) == (0xffffffff));
``````

It has to do with integer conversions.

When 0xffffffff (which is unsigned) is assigned to `c`, it undergoes an implementation-defined conversion because the value is out of range. On a two's complement system, this will typically mean that the representation will be applied directly to the destination. So now `c` has the value -1 with the representation 0xffffffff.

Now for the comparison. The constant `0xffffffff` is unsigned and has the value 232-1. When comparing a signed value with an unsigned value of the same size, the signed value is converted to unsigned. This happens (according to the standard) by adding the maximum value of an `unsigned int` + 1 to the signed value to put it in range. So the signed value -1 is converted to the unsigned value 232-1. This is the same value as 0xffffffff so the comparison is true.

8

Because `0xffffffff` on your platform is a value of type `unsigned int`. Therefore `0xffffffff >> 1` equals `0xffffffffU >> 1` which is `0x7fffffffU`.

When you assign a value of type `unsigned int` to a variable of type `int` the value is converted to the target type. `0xffffffff` i.e. 4294967295 is outside the range of a 32-bit signed integer, so naturally it cannot be stored as is. But because your computer uses two's complement system, the bits will remain the same, i.e. all bits will be set, but the value is interpreted as -1 instead of 4294967295.

The behaviour of right shift on negative integers is implementation-defined in the C standard. GCC defines it as arithmetic right shift, i.e. using sign extension. So the bit representation `ffffffff` shifted right by 1 will result in `ffffffff` bit representation; which as signed int signifies value `-1`.

Finally when you compare an `int` against an `unsigned int` using the `==` operator, the operands will undergo "usual arithmetic conversions" - the `int` -1 will be converted to an `unsigned int` - which on two's complement systems retains the bit pattern i.e. `ffffffff`, but now the value will be interpreted as 4294967295 instead of -1. But that value compares unequal to 0x7fffffff (2147483647), which has value

What is more confusing is that the value of `c` does not equal the `0xffffffff` even though the equality operator returns true! The value of `c` will be -1, and the value of `0xffffffff` is `0xffffffffu` i.e. `4294967295` and clearly the difference between `-1` and `4294967295` is 4294967296! But it is exactly because of the `signed/unsigned` comparison that different values can compare to equal - and for example GCC will warn about this with `-Wextra`:

``````warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
5 |   printf("%x\n", (c) == (0xffffffff));
|                      ^~
[venv][vrcappsdev][master✗]
``````

To see that the values indeed are distinct, you need to cast both sides to a type that is large enough to contain both of them - `long long int` is a portable one:

``````printf("%d\n", (long long int)c == (long long int)0xffffffff);
``````

will not print 1.

User contributions licensed under CC BY-SA 3.0