简体   繁体   中英

C++ integer conversion UB?

while doing some coding, I got a rather strange behavior, which seems du to UB, but I'm asking in case I missed something obvious. I compile this code with gcc 9,3, and -O3, in debug mode there is no problems

#include <array>
#include <climits>
#include <iostream>

void integer_overflow(long long v)
{
   unsigned long long uv;
   // removing the following comments here make the function works!
   //   if (v == LONG_LONG_MIN)
   //      uv = static_cast<unsigned long long>(v);
   //   else
   uv = (v < 0) ? -v : v;

   std::array<char, 40> buffer;

   auto last = buffer.rbegin();
   *last++   = '\0';
   if (v == 0)
   {
      *last++ = '0';
   }
   else
   {
      auto digits = 0;

      do
      {
         auto rem = uv % 10ULL;
         *last++  = rem + '0';
         uv /= 10ULL;
         if (uv != 0 && ++digits == 3)
         {
            *last++ = ',';   // comment this line, the loop work!, but not the good output!!!
            digits  = 0;
         }
      } while (uv != 0);
      // take care of neg values!
      if (v < 0)
         *last++ = '-';
   }
   std::cout << last.base() << std::endl;
}


int main(int argc, char** argv)
{
   integer_overflow(LONG_LONG_MIN + 1);   // ok
   integer_overflow(LONG_LONG_MIN);       // does not work
}

Output:

-9,223,372,036,854,775,807

-8

so my question how do I convert LONG_LONG_MIN to it positive counterpart in an unsigned long long?

also is that UB as I suspect? I think it is UB because -v for the smallest integral value on intel two's complement is probably undefined!

Completing @KamilCuk 's answer, one way you could convert an integer to its absolute value in the unsigned equivalent type is by casting it then negating it if it used to be negative.

Negating/under/overflowing an unsigned integer is always fine.

int32_t x;
uint32_t absOfX = x<0 ? -((uint32_t)x) : x;

Edit: following the deletion of the other answer, I complete this one - negating the minimum value of a signed integer type is indeed UB (see Is negating INT_MIN undefined behaviour? )

Similarly, so is taking its absolute value using the standard library function. The reference for std::abs mentions:

The behavior is undefined if the result cannot be represented by the return type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM