0

In C++, is it guaranteed that if I used the signed & unsigned versions of a fixed-width integer to perform an operation, I will get the same result? That is, if I do:

uint64_t a = [any number];
uint64_t b = [any number];
uint64_t resultOne = a + b;
uint64_t resultTwo = (uint64_t)(((int64_t) a) + ((int64_t) b));

Is it guaranteed that resultOne and resultTwo would always produce the same output no matter what values I use for a and b?

Lev Knoblock
  • 611
  • 2
  • 6
  • 20

1 Answers1

1

With unsigned types, addition is guaranteed to wrap around: if you add 1 to the maximum uint64_t, you get 0.

With signed types, in both C and C++, wraparound is undefined behavior: anything could happen, and in practice the compiler can do things you don't expect if you have optimization turned on.

So no, this is not guaranteed by the standard.

However, many compilers give an option to, as an extension to the standard, guarantee wrapped behavior for signed types, in which case the answer is yes. For example, see -fwrapv of GCC and Clang.

Daniel H
  • 7,223
  • 2
  • 26
  • 41
  • So in the case of using -fwrapv, equality would be guaranteed? – Lev Knoblock Apr 20 '19 at 04:20
  • @LevKnoblock It is, but I skipped over some details in my answer. If the unsinged value is outside the range of the signed type, the cast itself is [implementation-defined before C++20](https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_conversions); after that it'll be the value you expect. It turns out that [GCC's definition](https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/Integers-implementation.html#Integers-implementation) of this behavior is the same as the C++20 definition. – Daniel H Apr 20 '19 at 04:27