9

I arrived at a point where I need to compare singed and unsigned values. Until now I always modified the code base to avoid this situation completely, but now I can't do that.

So what is the really proper way to handle singed and unsigned comparison? This is a mixed C/C++ code base, so my question applies to both languages.

I'm checking a resource (signed) against requested value (unsigned).

if (requested > resource.max) return Never;
if (requested > resource.free - resource.assigned) return NotNow;
return Now;

I was thinking about something like this (substitute C++ variants where applicable):

if (requested > (unsigned)INT_MAX) bail_out(); // assert,abort,throw,return....
if ((signed)requested > resource.max) return Never;
if ((signed)requested > resource.free - resource.assigned) return NotNow;
return Now;

Am I approaching this correctly, or is there some better way?

EvilTeach
  • 28,120
  • 21
  • 85
  • 141
Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
  • Why is your resource count signed in the first place? – Jens Gustedt Jul 31 '12 at 08:23
  • 1
    How about `resource.free < resource.assigned + requested`? – Kerrek SB Jul 31 '12 at 08:24
  • 1
    Or why is requested unsigned since that's the value that the OP seems to want to treat as signed. Anyway this approach seems fine to me. This sort of stuff is so tedious that I tend to avoid unsigned types altogether. – jahhaj Jul 31 '12 at 08:25
  • If `requested` is greater than `INT_MAX` then it's definitely bigger than `resourse.max` so you *could* just return `Never`. Otherwise, you don't seem to have a problem here: once you checked the top bit isn't set, casting to `(signed)` is perfectly safe. – ams Jul 31 '12 at 08:43

1 Answers1

10

You can use this one-liner code as a starting point to do it safely:

bool GreaterSignedUnsigned( unsigned int u, signed int i )
{
   // calculate the result of (u > i)

   // if i is nonnegative it is safe to compare 2 unsigned values, 
   // otherwise unsigned int is always greater
   return  ( i < 0 ) || ( u > static_cast<unsigned int>(i) );
}

P.S. It is a good practice to avoid mixed signed/unsigned comparisons whenever possible since additional compare and a cast can cause a performance loss.

Sergey K.
  • 24,894
  • 13
  • 106
  • 174