Search code examples
ctype-conversionc99unsignedsigned

Is a type cast necessary while converting between signed int and unsigned int?


I tried assigning a signed int to unsigned int.

#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%d", &a);
  b = a;
  printf("%d %u\n", a, b);
  return 0;
}

I was hoping that compiling this would cause a warning that I am assigning an int value to unsigned int variable. But I did not get any warning.

$ gcc -std=c99 -Wall -Wextra -pedantic foo.c
$ echo -1 | ./a.out
-1 4294967295

Next I tried to assigning an unsigned int to signed int.

#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%u", &b);
  a = b;
  printf("%d %u\n", a, b);
  return 0;
}

Still no warning.

$ gcc -std=c99 -Wall -Wextra -pedantic bar.c
$ echo 4294967295 | ./a.out
-1 4294967295

Two questions:

  1. Why are no warnings generated in these cases even though the input gets modified during the conversions?
  2. Is a type cast necessary in either of the cases?

Solution

  • Code 1: This conversion is well-defined. If the int is out of range of unsigned int, then UINT_MAX + 1 is added to bring it in range.

    Since the code is correct and normal, there should be no warning. However you could try the gcc switch -Wconversion which does produce a warning for some correct conversions, particularly signed-unsigned conversion.

    Code 2: This conversion is implementation-defined if the input is larger than INT_MAX. Most likely the implementation you are on defines it to be the inverse of the conversion in Code 1.

    Typically, compilers don't warn for implementation-defined code which is well-defined on that implementation. Again you can use -Wconversion.

    A cast is not necessary and as a general principle, casts should be avoided as they can hide error messages.