More fun with Signed / Unsigned Comparisons

Here is why one should be very careful while mixing signed and unsigned integer comparisons. Take a look at this code snippet below:

#include <iostream>
#include <string>

int main(int argc, char *argv[])
        std::string presidentsOrders = "NO lets do more sanctions";
        unsigned int pos;

        pos = presidentsOrders.find("YES");
        if (pos != std::string::npos) {
                std::cout << "Lets nuke North Korea" << std::endl;
        } else {
                std::cout << "More sanctions (yawn)" << std::endl;
        return 0;

The President does not want to nuke North Korea, but lets see how the program actually interprets this. If you try compiling and executing this program in a 32-bit environment, it will work as it should:

abhi@devserver:~/cpp_string_pos$ ./a.out 
More sanctions (yawn)

Now compile the same program in a 64-bit environment (you can cross-compile using the -m32 or -m64 flag in g++). Here is the result:

abhi@devserver:~/cpp_string_pos$ g++ cpp_string_pos32.cpp -m64
abhi@devserver:~/cpp_string_pos$ ./a.out 
Lets nuke North Korea

So we effectively misinterpreted the order to fire the nuclear missile. The problem is that std::string::npos is a size_t type and usually defined as:

static const size_t npos = -1;

This is 0xFFFFFFFF on 32-bit, but becomes 0xFFFFFFFFFFFFFFFF on 64-bit. The comparison on 64-bit is then between the unsigned int pos which is upconverted to 0x00000000FFFFFFFF and 0xFFFFFFFFFFFFFFFF causing the check to fail and the nuke getting fired. So the right thing to do here is to use std::string::size_type for pos instead which would store the right value in the pos variable. This is of course an exaggerated example, and I do hope that missile systems have more levels of strict checks that need to be cleared before they get fired, but it showcases how disastrous this kind of mistake can be. Poor choices of data types for variables can really run your program into the ground.

Leave a Reply

Your email address will not be published. Required fields are marked *