```
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?

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 2^{32}-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 2^{32}-1. This is the same value as 0xffffffff so the comparison is true.

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 `-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