11

I have spent some time trawling this site; in particular this question: Is ((a + (b & 255)) & 255) the same as ((a + b) & 255)?

In doing so, I've been led to the conclusion that

int main()
{
    unsigned short i = std::numeric_limits<unsigned short>::max();
    unsigned short j = i;
    auto y = i * j;
}

can lead to undefined behaviour due to a type promotion of i and j to int which subsequently overflows upon the multiplication! Perhaps i and j need not to even be this large.

My conclusion is that, for example, on a system where unsigned short is 16 bits and int is 32 bits, the behaviour can be undefined.

Am I correct here?

Community
  • 1
  • 1

1 Answers1

12

Yes, it's possible, and your example is likely to be undefined on most desktop architectures.

For the sake of this example, let's assume that int is 32-bit 2's complement type and unsigned short is 16-bit.

I'm using N4140 for the quotes.

Before multiplication, both values are promoted to int:

§ 4.5 [conv.prom] / 1

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type;

Then:

§ 5 [expr] / 4

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

Since the result of 65535 * 65535 (4294836225) is not defined in our 32-bit int (with value range [-2147483648,2147483647]), the behaviour is undefined.

krzaq
  • 16,240
  • 4
  • 46
  • 61
  • 1
    It overflows on my PC where the above example is compiled with VS 2013. –  Nov 24 '16 at 11:57
  • Great answer! I think the promotion rules are one of the worst things (in terms of language design) in C that unfortunately got adopted by C++. They are the source of countless number of subtle bugs. Fortunately the compilers can warn sometime. – vsoftco Nov 24 '16 at 13:42
  • Wouldn't the type of the expression get promoted to `unsigned int` if the value cannot fit into an int? – David G Nov 24 '16 at 16:57
  • @0x499602D2 nope, I quoted The relevant paragraphs – krzaq Nov 24 '16 at 17:03
  • @vsoftco in case promotion alter the value (which is the only issue really), you can use the -Wconversion as explained here: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html – Thomas Legris Dec 06 '16 at 14:18