A few days ago I came across a bit of nasty behaviour when evaluating an expression performing a simple calculation on a signed and unsigned integer. Take the following C++ code snippet:
unsigned int nA = 10;
int nB = 11;
if( nA – nB < 0 )
On first inspection, given the inputs I would expect the expression to evaluate to true. What surprised me is that, despite no compiler warnings being emitted using Visual Studio 2010 at warning level 4, the statement evaluates to false.
It turns out the signed int is silently promoted to an unsigned int which changes things. The answer to 10 – 11 is no longer -1 but 4294967294 ( or UINT_MAX-1 ) since an unsigned integer can’t hold a negative number (no ‘spare’, top bit for sign indication) and has wrapped around.
There are a few different fixes depending on the what your function is trying to do. Assuming mixing signed and unsigned types is unavoidable, the following fix to this is simple assuming there can be no range violations and you won’t end up with a large negative number for the left hand side:
if( static_cast( nA ) – nB < 0 )
I understand that gcc does emit a warning about this with
-Wextra but the usual advice of test test test is hard to beat. Did I mention that I'm a huge fan of unit tests?