Lightness Races in Orbit Lightness Races in Orbit - 3 days ago 5
C++ Question

Why is this expression being unsigneded?

On x86_64 CentOS 7 GCC 4.8.5 C++11:

#include <iostream>

int main()
{
std::cout << ((ssize_t)1 - (size_t)5) << '\n';
}

// Output: 18446744073709551612


But:

#include <iostream>

int main()
{
std::cout << ((ssize_t)1 - (unsigned int)5) << '\n';
}

// Output: -4


And on i686 CentOS 6 GCC 4.8.2 C++11, they both give
4294967292
so I have to do this:

#include <iostream>

int main()
{
std::cout << ((ssize_t)1 - (ssize_t)5) << '\n';
}

// Output: -4


An extremely contrived example, obviously, and I understand that I'm hitting various clauses in the integral promotion rules depending on the platform/implementation-defined type equivalences, but on a Thursday my brain can't unravel them for a rigourous assessment.

What exactly is the sequence of standard rules that leads me to these results?

Answer

Assuming that ssize_t and size_t have equal rank, in your first case, [expr]/(11.5.5) applies:

Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

1 will be converted to the unsigned version of ssize_t, which should be size_t—hence the unsigned underflow, and the value of 2sizeof(size_t)*8-4.

For your second case, assuming that the rank of unsigned is less than that of ssize_t, and the latter can hold all of the former's values; see [expr]/(11.5.4):

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.

I.e. 5 will be converted to ssize_t, and so we get the negative result. If ssize_t is not of greater rank than unsigned, we'd get 2sizeof(unsigned)*8-4; if instead ssize_t could not hold all of unsigned's values, we get the negative result again, because we fall through to the aforementioned (11.5.5).

Comments