How does one safely static_cast between unsigned int and int?

Michael Kristofik picture Michael Kristofik · Sep 29, 2011 · Viewed 22.8k times · Source

I have an 8-character string representing a hexadecimal number and I need to convert it to an int. This conversion has to preserve the bit pattern for strings "80000000" and higher, i.e., those numbers should come out negative. Unfortunately, the naive solution:

int hex_str_to_int(const string hexStr)
{    
    stringstream strm;
    strm << hex << hexStr;
    unsigned int val = 0;
    strm >> val;
    return static_cast<int>(val);
}

doesn't work for my compiler if val > MAX_INT (the returned value is 0). Changing the type of val to int also results in a 0 for the larger numbers. I've tried several different solutions from various answers here on SO and haven't been successful yet.

Here's what I do know:

  • I'm using HP's C++ compiler on OpenVMS (using, I believe, an Itanium processor).
  • sizeof(int) will be at least 4 on every architecture my code will run on.
  • Casting from a number > INT_MAX to int is implementation-defined. On my machine, it usually results in a 0 but interestingly casting from long to int results in INT_MAX when the value is too big.

This is surprisingly difficult to do correctly, or at least it has been for me. Does anyone know of a portable solution to this?

Update:

Changing static_cast to reinterpret_cast results in a compiler error. A comment prompted me to try a C-style cast: return (int)val in the code above, and it worked. On this machine. Will that still be safe on other architectures?

Answer

ildjarn picture ildjarn · Sep 29, 2011

Quoting the C++03 standard, §4.7/3 (Integral Conversions):

If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.

Because the result is implementation-defined, by definition it is impossible for there to be a truly portable solution.