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.

È stato utile?

Soluzione

Operations on unsigned ints will result in unsigned ints. 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.

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;

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top