10

What happens if I do something like this:

unsigned int u;
int s;

...
s -= u;

What's the expected behavior of this:

1) Assuming that the unsigned integer isn't too big to fit in the signed integer?

2) Assuming that the unsigned integer would overflow the signed integer?

Thanks.

Colen
  • 13,428
  • 21
  • 78
  • 107
  • possible duplicate of [signed to unsigned conversion in C - is it always safe?](http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe) – Prasoon Saurav Mar 16 '11 at 17:09
  • Not a complete duplicate. That question had the last assignment into an `unsigned` variable, so the arithmetic is the same but the last assignment is different. – David Thornley Mar 16 '11 at 17:17
  • Also worth to have a look at: [*Is unsigned integer subtraction defined behavior?*](http://stackoverflow.com/q/7221409/1168156) :) – LihO Feb 24 '13 at 16:38

2 Answers2

15

In general, consult 5/9 in the standard.

In your example, the signed value is converted to unsigned (by taking it mod UINT_MAX+1), then the subtraction is done modulo UINT_MAX+1 to give an unsigned result.

Storing this result back as a signed value to s involves a standard integral conversion - this is in 4.7/3. If the value is in the range of signed int then it is preserved, otherwise the value is implementation-defined. All the implementations I've ever looked at have used modulo arithmetic to push it into the range INT_MIN to INT_MAX, although as Krit says you might get a warning for doing this implicitly.

"Stunt" implementations that you'll probably never deal with might have different rules for unsigned->signed conversion. For example if the implementation has sign-magnitude representation of signed integers, then it's not possible to always convert by taking modulus, since there's no way to represent +/- (UNIT_MAX+1)/2 as an int.

Also relevant is 5.17/7, "The behavior of an expression of the form E1 op= E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once". This means that in order to say that the subtraction is done in the unsigned int type, all we need to know is that s - u is done in unsigned int: there's no special rule for -= that arithmetic should be done in the type of the LHS.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Just a reminder that the "implementation defined result" could be an "implementation defined signal". (The C standard is much clearer in this regard.) In practice, you'll get the correct results on a two's complement machine, wrong results elsewhere. – James Kanze Mar 16 '11 at 17:20
  • @James: I think that's a deliberate difference between C++ and C, then. The C++ wording is quite clear, "the value is implementation-defined". It doesn't say, "the behavior is implementation-defined", which would permit a signal. – Steve Jessop Mar 16 '11 at 17:23
  • 1
    This answer is correct, but it has very surprising consequences. One is: **Even if the value of `u` is easily representable as `int`, it is implementation defined whether `s-=u` has the same effect as `s-=int(u)`.** This is because while converting signed to unsigned is precisely defined (by modular arithmetic), it is implementation defined whether the conversion back to signed will then reproduce the original value. So maybe even more surprising: **Even if `u==0`, it is implementation defined whether `s-=u` leaves `s` unchanged** in case `s` was negative. – Marc van Leeuwen Jun 01 '23 at 08:38
-2

u is recast as a signed integer and subtracted from s. Ultimately the casting doesn't make any difference. One set of bits is subtracted from the other and the result goes into s.

phkahler
  • 5,687
  • 1
  • 23
  • 31