using unsigned integers in c, c++

2018-02-21 12:01:54

I have a very simple question that baffles me for a long time. I am dealing with networks and databases so a lot of data I am dealing with are 32-bit and 64-bit counters (unsigned), 32-bit and 64-bit identification ids (also do not have meaningful mapping for sign). I am practically never deal with any real word matter that could be expressed as a negative number.

Me and my co-workers routinely use unsigned types like uint32_t and uint64_t for these matters and because it happens so often we also use them for array indexes and other common integer uses.

At the same time various coding guides I am reading (e.g. Google) discourage use of unsigned integer types, and as far as I know neither Java nor Scala have unsigned integer types.

So, I could not figure out what is the right thing to do: using signed values in our environment would be very inconvenient, at the same time coding guides to insist on doing exactly this.

There are two schools of thought on this, and

  • There are two schools of thought on this, and neither will ever agree.

    The first argues that there are some concepts that are inherently unsigned - such as array indexes. It makes no sense to use signed numbers for those as it may lead to errors. It also can impose un-necessary limits on things - an array that uses signed 32-bit indexes can only access 2 billion entries, while switching to unsigned 32-bit numbers allows 4 billion entries.

    The second argues that in any program that uses unsigned numbers, sooner or later you will end up doing mixed signed-unsigned arithmetic. This can give strange and unexpected results: casting a large unsigned value to signed gives a negative number, and conversely casting a negative number to unsigned gives a large positive one. This can be a big source of errors.

    2018-02-21 12:22:21
  • First of all, the Google C++ coding guideline is not a very good one to follow: it shuns things like exceptions, boost, etc which are staples of modern C++. Secondly, just because a certain guideline works for company X doesn't mean it will be the right fit for you. I would continue using unsigned types, as you have a good need for them.

    A decent rule of thumb for C++ is: prefer int unless you have a good reason to use something else.

    2018-02-21 12:28:24
  • The other answers lack real world examples, so I will add one. One of the reasons why I (personally) try to avoid unsigned types.

    Consider using standard size_t as an array index:

    for (size_t i = 0; i < n; ++i)

    // do something here;

    Ok, perfectly normal. Then, consider we decided to change the direction of the loop for some reason:

    for (size_t i = n - 1; i >= 0; --i)

    // do something here;

    And now it does not work. If we used int as an iterator, there would be no problem.

    I've seen such error twice in the past two years. Once it happened in production and was hard to debug.

    Another reason for me are annoying warnings, which make you write something like this every time:

    int n = 123; // for some reason n is signed


    for (size_t i = 0; i < size_t(n); ++i)

    These are minor things, but they add up. I feel like the code is cleaner if only signed integers are used everywhere.


    Sure, the examples look dumb, but I saw people making this mistake. If there's such an e

    2018-02-21 12:41:58
  • for (size_t i = v.size() - 1; i >= 0; --i)

    std::cout << v[i] << std::endl;

    The problem here is that you wrote the loop in an unclever manner leading to the erroneous behavior. The construction of the loop is like beginners get it taught for signed types (which is OK and correct) but it simply doesn't fit for unsigned values. But this cannot serve as a counter argument against using unsigned types, the task here is to simply get your loop right. And this can easily be fixed to reliably work for unsigned types like so:

    for (size_t i = v.size(); i-- > 0; )

    std::cout << v[i] << std::endl;

    This change simply reverts the sequence of the comparison and the decrement operation and is in my opinion the most effective, undisturbing, clean and shortes way to handle unsigned counters in backward loops. You would do the very same thing (intuitively) when using a while loop:

    size_t i = v.size();

    while (i > 0)


    std::cout << v[i] << std::endl;



    No underflow can occur,

    2018-02-21 12:43:19
  • Finally, I found a really good answer here: "Secure Programming Cookbook" by J.Viega and M.Messier (

    See recipe 3.5 - do not use signed numbers if possible.

    2018-02-21 12:58:42