Thomas Richter
6/9/2011 8:32:00 PM
On 09.06.2011 22:10, pozz wrote:
> What happens when I sum or subtract two unsigned integers?
The result is computed modulo 2^N.
> I think the
> operands are considered unsigned, because they are of the same type.
Yes.
> When I sum two unsigned integers the only problem could be an overflow.
Not in the sense that the result is undefined. The result will
wrap-around in a well-defined way. unsigned integers implement modulo
arithmetic. Overflows happen with signed arithmetic, and what happens
there is up to the implementation (including possibly a trap).
> When I subtract a lower from a bigger number, I won't have any problem.
>
> The problem is when I subtract a bigger from a lower number. If they are
> "small" numbers (lower or equal than INT_MAX), I can cast to (signed
> int). What happens when I subtract INT_MAX+1 from INT_MAX+2?
INT_MAX is not an unsigned number. You can first convert it to an
unsigned number, and then subtract. In that case, the result is +1,
always, and defined to be +1 for any conforming compiler. Note that this
is not guaranteed for signed integers.
> unsigned int x = INT_MAX + 2U;
> unsigned int y = INT_MAX + 1U;
> int diff = y - x;
This is not what you're writing above. Here you subtract INT_MAX
converted to unsigned, plus 2, from a INT_MAX+1. The result is the
largest possible unsigned number. You then convert it to a signed type
that cannot represent this value. What happens then is not defined by
the ANSI standard, but rather implementation defined. In your specific
case, with your specific compiler, complement arithmetic is used and the
result is interpreted as negative number modulo a power of two. But this
is, as said, not guaranteed by ANSI C, but (should be) by your compiler.
> printf("diff=%d\n", diff);
>
> I tried with one compiler and I obtain the correct result: diff=-1.
> Is this a standard behaviour or is it implementation defined/undefined
> behaviour?
It is implementation defined. x-y = 1U and y-x=MAX_UINT is standard defined.
> (y - x) is a binary expression between two unsigned variables, so they
> shouldn't be changed into signed variables.
So why do you convert it to a signed variable in first place? (-; You
are quite correct, the difference is indeed an unsigned int.
> So the result should be
> always unsigned... so what happens to -1?
A conversion of a valid value of an unsigned int which is not
representable by signed int. Up to the implementation to define what
then happens. For a machine using sign-magnitude representations for
ints, the result might possibly be the smallest (largest in absolute
value) negative number reprsentable by int, not -1.
unsigned int diff = y - x;
gives the right result, namely -1 + 2^N, for a suitable value of N.
Where N is, of course, defined by the implementation. However, *that*
you have modulo arithmetic here is, indeed, ensured by ANSI-C.
HTHH,
Thomas