A simple non-portable expression tha

Gregory Smith greg at utcsri.UUCP
Wed Apr 23 02:26:25 AEST 1986


In article <130 at brl-smoke.ARPA> gwyn at BRL.ARPA (VLD/VMB) writes:
>No, the compiler is not free to associate right-to-left in an
>expression
>	long + int + int.
>Addition associates left-to-right, and the integral widening
>conventions apply, so the middle term must be converted to long
>and added to the leftmost term before the rightmost term is
>added.  The compiler is allowed to reorder this only if it
>guarantees the same answer as would be obtained by following
>the rules.  On machines where integer overflow is ignored,

If this is strictly true, then the widening semantics are applied to
the expression tree before any reassociation is done:

long L; int I1,I2;

	L+I1+I2,  parses as (L+I1)+I2,
		  after widening is (L+(long)I1)+(long)I2

The compiler can still do this as L + ( (long)I1+(long)I2), though,
since everything is now the same width and so the result won't be affected.

>the opportunity arises more frequently than on those where
>it traps.  However, in this example, information could be
>lost by overflow if the compiler treated the expression as
>	long + (int + int)
>so it is not allowed to do that.

What if you *write* L+(I1+I2)? If the widening semantics *are* applied
before any reassociation is done, the result is L+(long)(I1 + I2),
using an integer add for I1+I2, which presumably may not be re-ordered
because the result would be affected - besides it is no longer of the
form a+(b+c).

However, I tried this ( using 16-bit short ints for I1,I2 ) on our
native vax compiler and on our 68K compiler. Both produced identical code
for (L+I1)+I2 and L+(I1+I2) and L+I1+I2: specifically, ((long)I1+L)+(long)I2.
I guess the a+b+c is recognized as a special case, and all three are widened
to a common width regardless of the original associativity.

Interestingly, writing the expression as L+(short)(I1+I2) had no effect on
the vax code, but forced the 68K compiler to do a 16-bit add of I1 and I2
before adding L. The 68K code is what I would expect - although deliberate
use of casts as %65536 operators is pretty shaky stuff.

A final question - It seems that L+I1+I2 will work regardless of if and
where you put the ()'s, since a 'chained' addition is treated as a
special case. But is this a feature of the language, or of the
compiler? Any 'portability' which is based on a non-essential compiler
feature is not really true portability, is it...?
-- 
"If you aren't making any mistakes, you aren't doing anything".
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg



More information about the Comp.lang.c mailing list