C++ unsigned int problems

By , last updated September 25, 2016

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.

Read also  Conjunctions and Disjunctions

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:

Comments

  1. Irfan September 25, 2016 Leave a Reply

    Hello Tatyana,
    You have concluded the first paragraph with the following sentence:
    but as a result may hold more values.
    Would it be possible for you to give an example or two where an unsigned type of the basic primitive type may not have the capacity to hold values greater than its original signed type. Considering that I have not used C++ in over 10 years, hence I can not say with certainty, however, I have an inkling that the unsigned derivatives, which only serve as compile–time guarantees, always have greater capacity than their corresponding signed counterparts.
    I would appreciate a response.
    Irfan.

    • Tatyana September 25, 2016 Leave a Reply

      Hello,
      I’ve tried to clear up some confusion by updating the article with more explanation and examples. Hope it helps.

  2. Irfan September 25, 2016 Leave a Reply

    Hello Tatyana,

    Thanks aplenty for promptly updating the article and removing some of the confusion.

    Having said that, I believe that the following sentence still needs your attention:

    my task was to make sure that a player has resources left after he destroys some items, for example, a wooden house.

    Considering that I am not a grammarian, hence I can not say with certainty, however, had you worded the sentence in the following manner, it probably would have been better:

    my task was to make sure that a player had (some or enough) resources left after he had destroyed some items, for example, a wooden house.

    In case of the following sentence, the offered correction would certainly state the outcome of the action in a manner that would align well with what actually happens:

    If you force a C++ unsigned int primitive into a negative state you will get a huge number.

    As far as I now know — required some further investigation owing to staleness of pertinent knowledge — the compiler actually assigns it the maximum possible value permitted for that particular unsigned type.

    Take care,

    Irfan.

Leave a Reply


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*