Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ safeness of code with implicit conversion between signed and unsigned

Tags:

c++

According to the rules on implicit conversions between signed and unsigned integer types, discussed here and here, when summing an unsigned int with a int, the signed int is first converted to an unsigned int.

Consider, e.g., the following minimal program

#include <iostream>

int main()
{
   unsigned int n = 2;
   int x = -1;

   std::cout << n + x << std::endl;

   return 0;
}

The output of the program is, nevertheless, 1 as expected: x is converted first to an unsigned int, and the sum with n leads to an integer overflow, giving the "right" answer.

In a code like the previous one, if I know for sure that n + x is positive, can I assume that the sum of unsigned int n and int x gives the expected value?

like image 767
francesco Avatar asked Nov 06 '18 22:11

francesco


People also ask

Is it safe to cast signed to unsigned?

When one unsigned and one signed variable are added (or any binary operation) both are implicitly converted to unsigned, which would in this case result in a huge result. So it is safe in the sense of that the result might be huge and wrong, but it will never crash.

How do you convert between signed and unsigned?

To convert a signed integer to an unsigned integer, or to convert an unsigned integer to a signed integer you need only use a cast. For example: int a = 6; unsigned int b; int c; b = (unsigned int)a; c = (int)b; Actually in many cases you can dispense with the cast.

What is the difference between unsigned and signed in C?

A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647]. An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295]. The signed integer is represented in twos complement notation.

Does C allow implicit conversion?

Implicit type conversion in C language is the conversion of one data type into another datatype by the compiler during the execution of the program. It is also called automatic type conversion.


2 Answers

In a code like the previous one, if I know for sure that n + x is positive, can I assume that the sum of unsigned int n and int x gives the expected value?

Yes.

First, the signed value converted to unsigned, using modulo arithmetic:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).

Then two unsigned values will be added using modulo arithmetic:

Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.

This means that you'll get the expected answer.

Even, if the result would be negative in the mathematical sense, the result in C++ would be a number which is modulo-equal to the negative number.

Note that I've supposed here that you add two same-sized integers.

like image 185
geza Avatar answered Oct 19 '22 07:10

geza


I think you can be sure and it is not implementation defined, although this statement requires some interpretations of the standard when it comes to systems that do not use two's complement for representing negative values.

First, let's state the things that are clear: unsigned integrals do not overflow but take on a modulo 2^nrOfBits-value (cf this online C++ standard draft):

6.7.1 Fundamental types

(7) Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.

So it's just a matter of whether a negative value nv is converted correctly into an unsigned integral bit pattern nv(conv) such that x + nv(conv) will always be the same as x - nv. For the case of a system using two's complement, things are clear, since the two's complement is actually designed such that this arithmetic works immediately.

For systems using other representations of negative values, we'll have to read the standard carefully:

7.8 Integral conversions

(2) If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is notruncation). —endnote]

As the footnote explicitly says, that in a two's complement representation, there is no change in the bit pattern, we may assume that in systems other than 2s complement a real conversion will take place such that x + nv(conv) == x - nv.

So due to 7.8 (2), I'd say that your assumption is valid.

like image 38
Stephan Lechner Avatar answered Oct 19 '22 06:10

Stephan Lechner