I am wondering if things like this :
int a = ...;
long b = ...;
if (a < b)
doSomethings();
always works (excepted for unsigned)
In this condition
if (a < b)
an object of type int
is always converted to the type long
provided that one of the operands has type long
because type long
has higher rank than type int
.
As for other types then according to the C Standard (6.5.8 Relational operators)
3 If both of the operands have arithmetic type, the usual arithmetic conversions are performed.
It means that after the integer promotion an operand with a lower rank is converted to the type of the other operand.
int/long
compare always works. The 2 operands are converted to a common type, in this case long
and all int
can be converted to long
with no problems.
int ii = ...;
long ll = ...;
if (ii < ll)
doSomethings();
unsigned/long
compare always works if long
ranges exceeds unsigned
. If unsigned
range was [0...65535]
and long
was [-2G...2G-1]
, then the operands are converted to long
and all unsigned
can be converted to long
with no problems.
unsigned uu16 = ...;
long ll32 = ...;
if (uu16 < ll32)
doSomethings();
unsigned/long
compare has trouble when long
ranges does not exceed unsigned
. If unsigned
range was [0...4G-1]
and long
was [-2G...2G-1]
, then the operands are converted to long
, a common type that does not encompass both ranges and problems ensue.
unsigned uu32 = ...;
long ll32 = ...;
// problems
if (uu32 < ll32)
doSomethings();
// corrected solution
if (uu32 <= LONG_MAX && uu32 < ll32)
doSomethings();
// wrong solution
if (ll32 < 0 || uu32 < ll32)
doSomethings();
If type long long
includes all the range of unsigned
, code could use do the compare with at least long long
width.
unsigned uu;
long ll;
#if LONG_MAX >= UINT_MAX
if (uu < ll)
#if LLONG_MAX >= UINT_MAX
if (uu < ll*1LL)
#else
if (uu32 <= LONG_MAX && uu32 < ll32)
// if (ll < 0 || uu < ll)
#endif