C++ unsigned int problems

By , last updated June 24, 2019

Primitives in C++ language can have signed and unsigned values. Signed means that they may be both positive and negative. Unsigned values may be only positive, but as a result may hold more values.

The term “more values” may be a bit misleading. The meaning is that unsigned values can hold larger values than signed ones. The number of values are identical.

Unsigned example

For integer types (not floating point types), the difference between signed and unsigned is that the first bit is the sign bit.

Using a 4-bit number as an example, with both unsigned and signed:

0000 is 0 in both signed and unsigned.
0111 is 7 in both signed and unsigned.
1000 is 8 in unsigned, and -7 in signed due to two-complement.
1111 is 15 in unsigned, and -1 with signed.

With a 32-bit int, a signed int has a range from −2,147,483,648 to 2,147,483,647. An unsigned int has a range from 0 to 4,294,967,295.

The reason unsigned values exist in C++ is because they come from C, and sometimes there are things which are more logically represented with unsigned numbers. Length of an array is one such thing. A negative length does not compute.

Unsigned values problems

There are several problems and pitfalls with unsigned values: sometimes they are error prone and lead to difficult to spot bugs and as other languages don’t have them it is more difficult to convert values.

Unsigned int bug example

Here is a real world example from our game. We were making a game and my task was to make sure that a player has resources left after he destroys some items, for example, a wooden house. It takes 4 “wooden items” to make a wooden house and I wanted it to be 3 wooden items left after it was destroyed. So I wrote the following code that loops though all items except for the last one:

unsigned int itemcount = item.getItemCount();
for (int i = 0; i < itemcount-1; i++)
{
   // some code
}

And the result was a stack overflow and an infinite number of items:

12:37:52 [debug] Created from group: 1, item: 0
12:37:52 [debug] Created from group: 1, item: 0
12:37:52 [debug] Created from group: 1, item: 0
12:37:52 [debug] Created from group: 1, item: 0
12:37:52 [debug] Created from group: 1, item: 0
...

What was wrong? Take a look at the code:

unsigned int itemcount = item.getItemCount();

Did you know the fact that (unsigned) 0 – 1 = 0xFFFFFFFF ? If you force a C++ unsigned int primitive into a negative state you will get a huge number.

0xFFFFFFFF – is a very big number

So, what was really written and why it went bad:

unsigned int itemcount = item.getItemCount();
for (int i = 0; i < big big number; i++)
{
   // some code
}

The code looped through an indefinite number of items and placed them into a container. Bad idea!

Be careful with unsigned numbers especially if you use subtraction operations. Use unsigned variable only if you really need them. Prefer signed variables otherwise.

Take a look at this talk with Bjarne Stroustrup where he tells just that: