Skip to main content

unsigned and size_t are hard.

This is a computer language story. So you are not interested in that, I recommend to go to next.

C++ has a type 'unsigned' X, e.g., 'unsigned int.' For example, a minus index of an array usually doesn't make sense, therefore this type is used for that. This type is good for bit array storage, but using an unsigned int instead of an int to gain one more bit is almost never a good idea. (*) Especially combination with implicit conversion makes this hard. I think this unsigned number is not intuitive when the computation result is minus, it still stays a positive number.

For example, unsigned int -1 is usually equal to 4294967295 on 32bit machine.  This is depends on how an integer number is represented in a computer. Even one who knows this internal representation wrote a code on 32bit environment, sometimes it doesn't work on a 64bit machine. For example, he/she assumes size_t and unsigned int are the same type, and uses -1 as an illegal value.

The following code usually doesn't work on a 64bit machine, but works on a 32bit machine.
---
#include <iostream>
#include <vector>

void foo(std::vector< int > & vec, size_t idx){
    if(idx == size_t(-1)){
        std::cout << "Illegal index" << std::endl;
        return;
    }
    std::cout << "OK! accessing a vector with idx = " << idx << std::endl;
    // vec[idx] = ...
}

int main()
{
    std::vector< int > vec;
    unsigned int idx = -1;      // illegal index
    foo(vec, idx);

    unsigned int uint_minus_1(-1);
    size_t   size_t_minus_1(-1);
    size_t   size_t_casted = static_cast< size_t >(uint_minus_1);

    std::cout << "(unsigned int)(-1)  = " << uint_minus_1   << std::endl;
    std::cout << "size_t(-1)          = " << size_t_minus_1 << std::endl;
    std::cout << "size_t(-1) (casted) = " << size_t_casted  << std::endl;
}
---
The result is as following. 
---
nvlp[16]bash % ./unsigned_fail
OK! accessing a vector with idx = 4294967295
(unsigned int)(-1)  = 4294967295
size_t(-1)          = 18446744073709551615
size_t(-1) (casted) = 4294967295
---

First of all, assign -1 to unsigned type is a problem. Also, implicit conversion makes invisible the problem. In C++ language, -1 has a different value according to the type. I think this is very difficult. Recent compiles might tell us this as a warning. I watch this warning since this is a potential error. One of my friend told me, "unsigned is evil." I also try to avoid unsigned type.

If you learn computer architecture, it sounds natural that -1 is equal to 4294967295. But, nowadays I try to think it is actually strange. If I think in that way, I could avoid the bugs in this example and I think I could write more portable and solid code.

(*) Bjarne Stroustrup, C++ Programming Language 3rd Ed. Section 4.4, paragraph 2. p.73

Comments

Erik said…
This post (from 2010 it looks like) is the first clear explanation I've been able to find on using size_t.

I can understand why, for example, conversion of a double to a size_t may not work even if the double is positive (an error that I've come across).

There is a bit of code, Matrix.cpp, written by Stroustrup where he mentions in his notes that he dislikes unsigned.

At the same time, I've come across a number of comments on other blogs that suggest using size_t in loops that index arrays may lead to a ~10 percent speed up.

From my experience, this seem generally not worth the problems that it causes.

Popular posts from this blog

Why parallelogram area is |ad-bc|?

Here is my question. The area of parallelogram is the difference of these two rectangles (red rectangle - blue rectangle). This is not intuitive for me. If you also think it is not so intuitive, you might interested in my slides. I try to explain this for hight school students. Slides:  A bit intuitive (for me) explanation of area of parallelogram  (to my site, external link) . 

Geometric Multiplicity: eignvectors (2)

If eigenvectors of a matrix A are independent, it is a happy property. Because the matrix A can be diagonalized with a matrix S that column vectors are eigenvectors of A . For example, Why this is a happy property of A? Because I can find A's power easily. A^{10} is not a big deal. Because Λ is a diagonal matrix and power of a diagonal matrix is quite simple. A^{10} = SΛ^{10} S^{-1} Then, why if I want to compute power of A ? That is the same reason to find eigenvectors. Eigenvectors are a basis of a matrix. A matrix can be represented by a single scalar. I repeat this again. This is the happy point, a matrix becomes a scalar. What can be simpler than a scalar value. But, this is only possible when the matrix S's columns are independent. Because S^{-1} must be exist. Now I come back to my first question. Is the λ's multiplicity related with the number of eigenvectors? This time I found this has the name. Geometric multiplicity (GM): the number of in...

Tezuka Osamu's Black Jack, "Shrinking"

I like several novel authors. My first favorite author is probably Teduka, Osamu. I still love him. The list grows by adding Hoshi, Shinichi, Agatha Christie, Hermann Hesse, and so forth. My first favorite article of Tezuka was Atom as most of the (boy's) Tezuka fans did. But my favorite is Black Jack. I try to summarize one story, it is still quite vivid in my memory. I first read this story when I was 13 - 15 years old. I re-read it at least several times since Black Jack is composed of many short episodes. The title should be "ちぢむ (SHRINKING)" or it might be "縮む(Shrinking)". (It is not so convenient to translate this to English, since English does not have a system to say the exact same word in several ways. So I just simulate it with capital letters.) Black Jack is a genius surgeon, but he does not have the license. In short, his medical activity is illegal. His skill is top level in the world, but, the fee is also out-of-law expensive. In the story ...