Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Casting inside a ternary operator causes underflow

I have the following snippet of code

   #include <iostream>

   int main() {

   int64_t res;
   int some_val = 5;

   if(false)
   {
       res = static_cast<uint32_t>(some_val);
   }
   else
   {
       res = -1;
   }
   std::cout << "first check: " << res << std::endl;

   res = (false) ? static_cast<uint32_t>(some_val) : (-1);
   std::cout << "second check: " << res << std::endl;

   return 0;
}

To my surprise, the stream output is:

first check: -1

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

second check: 4294967295

whereas I would’ve expected both checks to return -1, given that they’re basically the same exact expression.

I read the documentation and it says that the operator "?" should convert the 2 values to a common type, so I would’ve expected int64_t to be picked(which would allow for both datatypes to be represented) but this is clearly not the case and instead uint32_t is chosen, which causes the underflow when casted to -1.

Can someone explain to me what’s going on here?

>Solution :

The conditional operator converts its operands to a common type. In your case:

res = (false) ? static_cast<uint32_t>(some_val) : (-1);

The two sides of conditional operator are of type uint32_t and int respectively. Assuming that uint32_t is a type alias for unsigned int, the -1 (of type int) is converted to unsigned int.
In other words, the statement is equivalent to:

res = static_cast<int64_t>(false ? static_cast<uint32_t>(some_val)
                                 : static_cast<uint32_t>(-1));
// due to the "false ?", this is equivalent to:
res = static_cast<int64_t>(UINT32_MAX - static_cast<uint32_t>(1));

int64_t can represent all values of uint32_t, so the conversion uint32_t -> int64_t doesn’t change the value.

Converting int to unsigned in such cases is decision that dates back to C (see also What happens when I mix signed and unsigned types in C++?).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading