Unsigned considered harmful

(or is "xxx considered harmful" completely worn out as a meme?) 

 

I believe that, in general, people should avoid unsigned variables, even when dealing with quantities which should only be positive. I have three major problems with unsigned variables:

 

Subtraction doesn't always make sense

Unsigned numbers are used to model positive integers and positive integers aren't closed under subtraction.While subtracting two integers always gives another integer, subtracting two positive integers doesn't always give a positive integer. Integer subtraction is much more useful than positive integer subtraction!

 

Of course with wraparound the subtraction gives an unsigned integer, but that doesn't make arithmetic sense. Signed integers have the same problem, but only at the extremes where wraparound occurs. Even with idealized infinite-bit-length numbers subtraction of unsigned integers is problematic.

 

Lack of Error-checking on underflow

If subtraction does underflow most systems won't generate a runtime exception if they go negative (which would be useful), instead they silently wrap-around (which is not useful). In the end unsigned variables simply alias invalid negative values to positive ones.

 

Lack of Invalid Values

It is extremely useful when a type has support for a clearly invalid/unused value. This can be used both for error-checking and loop termination. Take a loop that iterates through a string backwards:

 

int IchLastCommaInString(const char * const sz) {

    int cch = strlen(sz);

    for(int i = cch-1; i >= 0; --i) {

        if(',' == sz[i]) {

            return i;

        }

    }

    return -1;

}

 

If we change the code to use an unsigned variable ("Array indexes can never be negative!") then we lose the ability to easily detect the termination condition:

 

int IchLastCommaInString(const char * const sz) {

    int cch = strlen(sz);

    for(unsigned int i = cch-1; i >= 0; --i) {  <= BAD! unsigned ints are always >= 0

        if(',' == sz[i]) {

            return i;

        }

    }

    return -1;

}

 

To use an unsigned variable we often end up on the dark and dismal path of "if(x > BIGNUM)" where BIGNUM is chosen to be a value so large that we 'know' that x is really a negative number in disguise.

 

Just use signed variables.