From: Anthony Williams (anthwil_at_[hidden])
Date: 2002-08-28 03:37:07


> What is the type of the sub expression "a*b"? If it is an "int" it needs
> to hold a specific number of bits, which is not to exceed the number of
> bits held by "long".

Given:

int a,b,c;

a*b on its own is of type int, and may overflow, which is undefined behaviour.
a*b/c is still of type int. If a*b overflows this is still undefined behaviour
by the standard, so a compiler may therefore use 2*sizeof(int) precision for
the interim value, in order to get a correct result e.g. (on x86)

mov eax,val1
mov ebx,val2
mov ecx,val3
imul eax,ebx
idiv ecx

which works in all non-overflowing cases, produces the correct result
where a*b/c fits in an int, and produces a divide-by-zero error (!) when the
result overflows. This is as opposed to

mov eax,val1
mov ebx,val2
mov ecx,val3
imul eax,ebx
cdq
idiv ecx

which just produces essentially random results where a*b overflows, but never
overflows. However, it is one more instruction, so there is a performance
penalty.

> What I am opposing is the 2^32 (or whatever the cardinality of "int" is
> on the particular platform) out-of-band values.

Fair enough. My point is that at least on x86, the optimal instruction
sequence has the property that a*b/c is well-defined if it fits in an int,
even when a*b overflows, and that this is acceptable by the C++ Standard, as
one possible instance of the undefined behaviour that ensues when a*b
overflows.

> Well, I thought C++ was a strongly typed language in the extended sense
> of each (sub)expression confining to one type... If the "a*b/c" is
> allowed to transcend those types in between the sub expression and the
> full expression, then I know better.

In the case of undefined behaviour, all bets are off, and the C++ compiler can
do what it likes. However, if it can do something useful, then it makes sense
to do so.

Anthony