# Unsigned Arithmetic: Useful but Tricky

C++, like C, supports two distinctly different kinds of integers: signed and unsigned. Each kind comes in several sizes, but the kinds differ in ways that transcend size. If a signed integer overflows, the result is undefined. If an unsigned integer overflows, the result is defined modulo 2^{w}, where `w`

is the number of bits in that particular unsigned integer. By implication, an unsigned integer is never negative.

In general, arithmetic that combines signed and unsigned values yields an unsigned result. This property is particularly important for comparisons, in which a signed integer is converted to unsigned for comparison purposes. For example, the comparison `n>=0u`

, where `0u`

represents an unsigned integer zero, is always true — even if `n`

is signed — because `n`

is converted to unsigned and the result of that conversion cannot be negative.

This aspect of how unsigned arithmetic behaves has some curious effects on programming technique. For example, suppose I have a vector named `x`

, and I want to access its `n`

th element. I do so by writing `x[n]`

, of course.

Suppose further that `n`

has type `int`

, and that I want to be sure before I try to access `x[n]`

that `n`

is in range. The obvious way of doing so is to write something like this:

if (n < 0 || n >= x.size()) throw an out-of-range exception; // Now it is safe to access x[n]

There is a subtle improvement possible in this code. The `size`

member of the `vector`

class returns an `unsigned`

value. When we compare `n`

to such a value, and `n`

has a signed type, `n`

will be converted to `unsigned`

for the comparison. If `n`

is negative, this conversion will wrap around and yield a large positive number. Only if `x`

has more elements than this number will the test succeed. As a result, so long as `x`

is not a huge negative number, we can omit the comparison `n `

.

Omitting the test this way is slightly shaky, because it *is* possible that `n`

might be such a large negative number as to wrap around and look like a large positive number. However, if we make `n`

unsigned, then we can definitely omit the comparison of `n`

to 0, because of course an unsigned variable will never be less than zero.

As so often happens, the code simplification that comes from making `n`

unsigned can complicate other kinds of programs. Suppose, for example, that we want to visit the elements of `x`

in reverse order. We cannot write

for (auto n = x.size() - 1; n >= 0; --n) // Do something with x[n]

because the comparison `n >= 0`

will always be true. The reason is that `x.size()`

yields an unsigned value, so `n`

will also be unsigned.

Instead, it is necessary to write something like this:

auto n = x.size(); while (n) { --n; // Do something with x[n] }

It is no coincidence that this technique is similar to the technique that one would use for iterators. In fact, there's an interesting story behind this similarity. I'll talk about that next week.

## Comments:

2012-06-08T16:52:37

An interesting problem occurs when you subtract an unsigned integer from a signed integer and use the result as a stream seek position. If the result would be negative, the result is not what you expect, and your code seeks to a position beyond the size limit.

The workaround is to always add 0L up front.

Permalink

2012-06-06T14:51:15

I share @YDONG000's comment. It would be great if Andrew could clarify it.

Also, there seem to be missing comparison at the end of this line:

"(...) we can omit the comparison n ."

Permalink

2012-06-04T03:25:44

A little confuse on "As a result, so long as x is not a huge negative number, we can omit the comparison n ." x is a vector, how did it be a negative number, on this part, did you means if n is a negative it will became a huge positive number, in common it will larger than x.size(), so we can skip n < 0. Am I right?

Permalink