Operations on unsigned int
s will result in unsigned int
s. Even the subtraction will yield an unsigned int
. the value just wraps around: unlike signed integer arithmetic, overflow and underflow for unsigned values results in well define behavior: the arithmetic is simply modulus N
where N
is one plus the maximum value which can be represented by the unsigned integer.
Where is the sign conversion occurring?
Domanda
I have the following code:
unsigned int x, last_x;
int dx;
[...]
dx = x - last_x;
Compiling this with g++ (4.7.2) and -Wsign-conversion produces the following:
warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion]
The only way to make the warning disappear is by changing to:
dx = static_cast<int>(x) - static_cast<int>(last_x);
or
dx = static_cast<int>(x - last_x);
What is the explanation for this behaviour? Is the -
operator only defined for signed ints? I would expect to have a -
operator that takes unsigned values and returns a signed value.
Soluzione
Altri suggerimenti
The compiler is warning you that the statement you entered, dx = x - last_x;
, could result in an unintended sign change. That means when you execute x - last_x
, which will be a positive number, when you convert it to a int
and store it in dx
the value may become negative.
Consider changing unsigned int x, last_x;
to int x, last_x;
.
The warning is trying to warn you that things can go wrong! Consider:
unsigned int x = UINT_MAX;
unsigned int last_x = 0;
int dx = x - last_x;
Obviously the difference is UINT_MAX
, but that doesn't fit in an int, so you get the (presumably undesirable) result of -1
.
The only time this will work as intended is if x
is part of a circular sequence (eg, a clock rolling over), in which case you should use
int dx = static_cast<int>(x - last_x);
But not
int dx = static_cast<int>(x) - static_cast<int>(last_x);
as that could cause signed integer overflow - undefined behavior
Since you are dealing with unsigned
integers, you will have to take precautions when subtracting to avoid negative results:
if (x > last_x)
{
dx = x - last_x;
}
else
{
dx = last_x - x;
}
As others have stated, a negative result would cause wrap-around.
Edit 1:
If you want dx
to be the signed result, you should cast the other values to signed int
before subtraction:
dx = (signed int)x - (signed int) last_x;