I have searched this site for an answer and found many responses to unsigned/signed comparison but this problem is that only unsigned parameters are compared but still it wo
In the expression:
if( (u16_varLow - u16_varHigh) > (unsigned short)5 )
(u16_varLow - u16_varHigh)
will be promoted to an int
and evaluate to -65525. The fix for your problem is to cast to an unsigned type, like you do in the "Does enter"-code.
The reason s16_Res1 = u16_varLow - u16_varHigh;
yields 11 is that the result of the subtraction, -65525, doesn't fit in a short.
The first one, if( (u16_varLow - u16_varHigh) > (unsigned short)5 )
will never pass, as (u16_varLow - u16_varHigh)
returns negative number, because it's treated as an integer. The second one casts the same negative number, to unsigned short, that's why it passes.
Note - you know that all this is platform-dependent, right? The size of short
, int
, etc. depends on the concrete platform.
In the other answers we have seen that
u16_varLow - u16_varHigh
for you (with 16 bit short
and 32 bit int
) is equivalent to
(int)u16_varLow - (int)u16_varHigh
and thus its result is the int
value -65525
. Thus the assignment
s16_Res1 = u16_varLow - u16_varHigh;
is equivalent to
s16_Res1 = -65525;
which in your case of 16 bit short
yields "undefined behavior". You are just unlucky that your compiler decides to assign 11
, instead. (Unlucky because I think that it is better to fail early.)
In contrast to that
u16_Res1 = -65525;
is a valid assignment since u16_Res1
is of an unsigned type and arithmetic of unsigned types is modulo the appropriate power of two.
In the "usual arithmetic conversions", types smaller than int
are promoted to either int
or unsigned int
before they are used in most expressions. The rule is that if int
can represent all the values of the smaller type, then it is promoted to int
; otherwise it is promoted to unsigned int
. This is often considered something of a wart, because in many cases it causes unsigned char
and unsigned short
values to be promoted to int
.
This is exactly what you're seeing - u16_varLow
and u16_varHigh
and (unsigned short)5
are all promoted to int
before the subtraction and comparison, which then happen using int
. If you wish to be certain that an expression will use unsigned arithmetic, you must do it in unsigned int
, not unsigned short
:
if( ((unsigned)u16_varLow - (unsigned)u16_varHigh) > 5U )