Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site utcsri.UUCP Path: utzoo!utcsri!greg From: greg@utcsri.UUCP (Gregory Smith) Newsgroups: net.lang.c Subject: Re: A simple non-portable expression tha Message-ID: <2609@utcsri.UUCP> Date: Tue, 22-Apr-86 11:26:25 EST Article-I.D.: utcsri.2609 Posted: Tue Apr 22 11:26:25 1986 Date-Received: Tue, 22-Apr-86 11:57:45 EST References: <130@brl-smoke.ARPA> Reply-To: greg@utcsri.UUCP (Gregory Smith) Organization: CSRI, University of Toronto Lines: 54 Summary: I tried it, and... In article <130@brl-smoke.ARPA> gwyn@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