4
#include <stdio.h>
#include <stdlib.h>
typedef    unsigned     int    U32;
int main() {
    U32 var     = -1;
    printf("var = %u\n", var);
    if(var != -1)
    {
        printf("\n I'm not -1\n");
    }
    else
    {
        printf("I'm -1 and Var :%u\n", var);
    }
 }

Here "-1" should be converted into an unsigned int and it should be assigned to var. And then at the if condition it should not be equal to -1. But it is going into the else statement.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

3 Answers3

3

Please note that all integer constants such as 1 have a type. Given that U32 is unsigned int, then:

  • In the case of U32 var = -1; (assignment), the right operand of type int is converted to the type of the left operand.

  • In the case of if(var != -1), the -1 operand is converted from type int to unsigned int as per the usual arithmetic conversions, details here: Implicit type promotion rules

In both cases, a signed to unsigned conversion occurs and such a conversion is well-defined as per 6.3.1.3:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

Meaning that in both cases above, the same unsigned value 0xFFFFFFFF will be generated.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Lundin
  • 195,001
  • 40
  • 254
  • 396
2

In this statement

if(var != -1)

the compiler needs to determine the common type of the operands. This process is named the usual arithmetic conversions. From the C Standard (6.5.9 Equality operators)

4 If both of the operands have arithmetic type, the usual arithmetic conversions are performed....

And relative to the usual arithmetic conversions (the C Standard, 6.3.1.8 Usual arithmetic conversions)

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

So according to the quote in the expression of the if statement the integer constant -1 having the type int is converted to the type unsigned int that is to the type of the variable var because the types int and unsigned int have the same rank and the variable var has the type unsigned int.

As a result the condition yields false.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
-2

An int, be it signed or unsigned is represented by a series of bits, like

B1B2...Bn

where

Bi ∈ {0; 1}

now, the biggest representable unsigned int looks like

1111...1

however, as a signed value, -1 is represented by

1111...1

as well

so, 1111...1 == 1111...1 is true. The conversion into unsigned did not change any values, it changes the way the given value is perceived. And in terms of memory representation 2^(32-1) and -1 is effectively the same dude, dressed in different clothes.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • 1
    I'm not sure how relevant this is, because all that matters here is how the integer conversion is carried out. For example `(long long)-1 == (unsigned long long)-1` is always true but `(long long)-1 == (unsigned int)-1` is always false. – Lundin Oct 17 '19 at 10:39