tobi303 - 1 year ago 84
C++ Question

# Assign negative of unsigned to a signed, is it OK?

When I run this:

``````int main() {
unsigned a = 5;
std::cout << -a << std::endl;
int b = -a;
std::cout << b << std::endl;
return 0;
}
``````

I get this:

``````4294967291
-5
``````

It seems like it works, and I can take the negative of an
`unsigned`
and assign it to an
`int`
, but is this really always OK? Why?

When I try something that to me looks like a similar situation:

``````int c = 1;
int d = 3;
double x = c/d;
std::cout << x << std::endl;
``````

I get
`0`
(as expected).

PS: Maybe there is a dupe and I didnt find it, closest I could find is this

No. You have undefined behaviour possibilities.

Here is a counter-example that produces UB when assigning a negated `unsigned int` to an `int`:

``````unsigned u = (unsigned)std::numeric_limits<int>::max() - 1;
std::cout << "max int" << std::numeric_limits<int>::max() << '\n';
std::cout << "as unsigned - 1" << u << '\n';
std::cout << "negated:" << -u << '\n';
std::cout << std::boolalpha << ( std::numeric_limits<int>::max() < -u ) << '\n';
int s = -u;
std::cout << s << '\n';
``````

On my machine: `int`'s max value is 2'147'483'647, but the negated `unsigned int` has a value of 2'147'483'650; that value is greater than the max value that can be represented by an `int`. Know that signed overflow is undefined behaviour. Thus, the algorithm is not safe for all of its possible values.

The Standard's (2016-07-12: N4604) word:

If during the evaluation of an expression, the result is not mathematically deﬁned or not in the range of representable values for its type, the behavior is undeﬁned. [ Note: Treatment of division by zero, forming a remainder using a zero divisor, and all ﬂoating point exceptions vary among machines, and is sometimes adjustable by a library function. — end note ]

In the future, you can use the `{}`-style initialization to prevent such issues:

``````unsigned a = 5;
std::cout << -a << '\n';
int b{ -a }; // compiler detects narrowing conversions, warning/error
std::cout << b << '\n';
return 0;
``````

Note that even though you know that `-a` will be a value that can be represented by an `int`, your compiler still warns you.

On signed overflow:

Is signed integer overflow still undefined behavior in C++?

On well defined unsigned overflow in both C and C++:

Why is unsigned integer overflow defined behavior but signed integer overflow isn't?

On implicit conversions:

http://en.cppreference.com/w/cpp/language/implicit_conversion

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download