Author Topic: Unsigned conversions  (Read 5129 times)

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Unsigned conversions
« on: February 20, 2019, 10:51:52 PM »
In C, comparing a i32 with an u32 will do the somewhat counterintuitive thing of promoting the i32 to u32.

This leads to the somewhat confusing situation that the following C code:

Code: [Select]
  int a = -1;
  unsigned int b = 1;
  unsigned short c = 1;
  if (a < b) printf("Less!\n");
  if (a > b) printf("More!\n");
  if (a < c) printf("Less short!\n");
  if (a > c) printf("More short!\n");

Prints:

More!
Less short!

The following rules might help:

1. The comparison operations < > <= >= are not allowed between signed and unsigned where the promotion would be to unsigned (that is, where the unsigned type is has greater or equal bit size of the signed). So i32 < u16 is fine, but not i32 < u32 or i16 < u32.

2. >= 0 is always an error for unsigned numbers. This would prevent the following bug: for (unsigned i = size; i >= 0; i--). The analyser should detect this condition as always being true and creating an *error* for it.

A more drastic change that could be considered instead of (1) would be to always do sign promotion whenever there is a comparison with signed and unsigned values.

So !i32 < u64) would cast both sides to i64. The downside of that (or any similar scheme) is that it differs from C in a critical, rarely learned part of the language. It feels dangerous. Prohibiting conversions feel more "safe". Note that comparisons (except for ==) is where the conversion from signed to unsigned is where the danger is. For example cast<i32>(-1) + cast<u64>(12) will still yield 11 as expected due to the behaviour of unsigned arithmetics.