2

If I cast an unsigned integer to a signed integer then cast back, am I guaranteed to get the original value? For example, does this function always return true for any x on any platform according to the C++ standard?

bool f(unsigned int x)
{
    return x == static_cast<unsigned int>(static_cast<int>(x));
}

What about this one?

bool g(int x)
{
    return x == static_cast<int>(static_cast<unsigned int>(x));
}
EFanZh
  • 2,357
  • 3
  • 30
  • 63
  • @sleeptightpupper I've made a mistake in my code. Sorry for the misleading. – EFanZh May 26 '16 at 02:03
  • I wasn't asking about that. I'm asking for what interval of values you're worried about. i.e, a negative value for `f` will obviously underflow so you will obviously not get the same value back. – uh oh somebody needs a pupper May 26 '16 at 02:04
  • @sleeptightpupper - you should try this with negative values yourself. You'll be shocked and surprised at the results. – Sam Varshavchik May 26 '16 at 02:05
  • @SamVarshavchik `f(-1)` gives me `4294967295`. I don't find that very surprising. Either way, it's "undefined behavior". – uh oh somebody needs a pupper May 26 '16 at 02:07
  • @sleeptightpupper I've modified my code before my first comment, please notice that. – EFanZh May 26 '16 at 02:08
  • 3
    @sleeptightpupper It's not undefined behavior, it is implementation-defined behavior. – Sergey Kalinichenko May 26 '16 at 02:13
  • @EFanZh use your debugger and watch the values change / or not change. That should answer your question. – NonCreature0714 May 26 '16 at 02:15
  • @dasblinkenlight ["If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined."](http://eel.is/c++draft/expr#4) – uh oh somebody needs a pupper May 26 '16 at 02:15
  • So, what have you tried? or perhaps, what were the results of either test? Did you cout a table of the results of static_cast<>? I suppose there are 8 tests ... both directions ... MAX, MIN, 0, ... etc. What did you find out? – 2785528 May 26 '16 at 02:16
  • @sleeptightpupper - how could f(-1) possibly give you that, when it computes a comparison operation, which is a boolean operation that can return 0 or 1. With `gcc 5.3.1`, your `f(-1)`, in the code you showed, returned `1`. One of us is very, very confused. – Sam Varshavchik May 26 '16 at 02:18
  • @SamVarshavchik You do realize the question's been edited right? – uh oh somebody needs a pupper May 26 '16 at 02:19
  • @sleeptightpupper What does it have to do with this question? OP talks specifically about conversions, this is discussed separately. – Sergey Kalinichenko May 26 '16 at 02:19
  • Yes, @sleeptightpupper, and `f(-1)` is still doing a `==` comparison, as shown in this question. – Sam Varshavchik May 26 '16 at 02:20
  • 2
    "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." – Raymond Chen May 26 '16 at 02:28
  • Aside from initially tagging this question C - which over complicated things, this is a very interesting post and a deserving of up votes. – chux - Reinstate Monica May 26 '16 at 02:42

1 Answers1

7

The answer is "no, this is not guaranteed" for both f and g.

Here is what the standard says about it:

4.7 Integral conversions

  1. If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). — end note ]
  2. If the destination type is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined.

Section 2 talks about function g. The cast of x to unsigned can cause change of representation on systems that do not use two's complement representation, so converting the number back may get you a different value.

Section 3 talks about function f. When the number is outside signed int's range, the result is implementation-defined, so one is not allowed to make any claims about the result of converting it back to unsigned.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523