Boost logo

Boost :

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk