2

When I assign the same value to signed and unsigned short and do a comparison it fails but it works with int. Unless I cast one or the other to make them same types the comparison is not working.

#include<stdio.h>

int main()
{
    signed short b = -10;
    unsigned short  c=-10;
    signed int a = -10;
    unsigned int d=-10;

    printf("%d , %d\n",b,(unsigned short)b);
    printf("%d , %d\n",(signed short)c,c);
    printf("%d , %u\n",a,(unsigned int)a);
    printf("%d , %u\n",(signed int )d,d);
    printf("b==c %d\n", b==c);
    printf("a==d %d\n", a==d);
    return 0;
}

Output:

./a.out
-10 , 65526
-10 , 65526
-10 , 4294967286
-10 , 4294967286
b==c 0
a==d 1

I ran this in sun solaris sparc and hpux itanium with same output. (64 bit exes)

Wolf
  • 9,679
  • 7
  • 62
  • 108

1 Answers1

7

This is because of the integer promotions rules of C.

Here is what's going on: when you try comparing two variables of different types, the compiler checks if each type can be promoted to an int. A type can be promoted to int when all its possible values fit into an int. If a type can be promoted to an int, it is promoted to an int; otherwise, the compiler checks if it can promote the type to an unsigned int. If this promotion is possible, the value is promoted to unsigned int before proceeding with the comparison.

In your first example both signed short and unsigned short can be promoted to an int. Once this is done, your get different values, so the comparison returns false.

In your second example, however, no promotions are done, because int cannot hold all values of unsigned int and vice versa. The "raw" comparison is performed, which compares the same representations and returns true.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks a lot! That explains it. Perfect! – chandra sekhar Sep 12 '14 at 15:20
  • The rules are a bit trickier than that. It would be legal for a platform to define both `int` and `long` to be 35 value bits plus a sign bit, and both `unsigned int` and `unsigned long` to be 35 value bits plus a padding bit. On such a platform, an operation between `int` and `unsigned long` would convert both operands to `unsigned long` (*even though `int` could represent all values of `unsigned long`!*), but an operation between `long` and `unsigned int` would convert both operands to `long` (even though `unsigned int` was the same size as `unsigned long`). – supercat Aug 12 '15 at 17:08