jkrueger@daitc.ARPA (Jonathan Krueger) (06/25/88)
Here's a question of portability and language standards that came up in
a real life program. According to K&R or ANSI, predict the output of
the following code:
#define DEFCONST 1.05
main()
{
int count = 800;
printf("count is %d, ", count);
count *= DEFCONST;
printf("now %d\n", count);
}
My prediction, based on K&R, was the output:
count is 800, now 839
Indeed, the Pyramid 98x produces exactly this output.
But your mileage may vary. 4.2BSD VAX, Gould, and Sun-3 produce output:
count is 800, now 800
Which brings me to the question: is this code non-portable, or do
three out of four compilers surveyed fail to correctly implement K&R?
The relevant K&R references appear to be 2.10, Assignment Operators
and Expresssions:
"If e1 and e2 are expressions, then
e1 op= e2
is equivalent to
e1 = (e1) op (e2)
except that e1 is computed only once."
and 2.7, Type Conversions:
"float is converted to double, then if either operand is
double, the other is converted to double, and the result
is double"
Putting it all together, does "e1 is computed only once" imply lack of
ordinary automatic type conversion for e1 and expressions of which it
is a part? Or does "computed" mean "value derived for", and K&R
in no way implies different type handling from the unabbreviated
expression? And does ANSI clear up this ambiguity?
-- Jon Krueger
ken (Ken Yap) (06/25/88)
I can't repeat your problem. What OS version have you? What compilers?
Script started on Fri Jun 24 19:49:06 1988
cursa.cs.rochester.edu% cat y.c
#define DEFCONST 1.05
main()
{
int count = 800;
printf("count is %d, ", count);
count *= DEFCONST;
printf("now %d\n", count);
}
cursa.cs.rochester.edu% cc -o y y.c
cursa.cs.rochester.edu% ./y
count is 800, now 840
cursa.cs.rochester.edu%
script done on Fri Jun 24 19:49:30 1988
Cursa is a Sun 3/50 running SunOS 3.4. On a Vax 11/750 running BSD 4.3
it gives
count is 800, now 839
Ken
gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/25/88)
In article <133@daitc.ARPA> jkrueger@daitc.ARPA (Jonathan Krueger) writes: >My prediction, based on K&R, was the output: > count is 800, now 839 >Indeed, the Pyramid 98x produces exactly this output. >But your mileage may vary. 4.2BSD VAX, Gould, and Sun-3 produce output: > count is 800, now 800 There is no ambiguity; the Pyramid has produced the correct answer and the other three compilers are wrong. The SVR2 VAX PCC also gets this right, so presumably all recent 3B CCSes do also. The code is "portable" to correct compilers. Obviously it is not "portable" to ALL compilers, as you have shown. Nag your system vendors to fix their compilers.
chris@mimsy.UUCP (Chris Torek) (06/27/88)
In article <133@daitc.ARPA> jkrueger@daitc.ARPA (Jonathan Krueger) writes: [only the following three lines are needed] >#define DEFCONST 1.05 > int count = 800; > count *= DEFCONST; The correct result is 840 (or something nearby, such as 839, depending on roundoff error). >Indeed, the Pyramid 98x produces exactly this output. >But your mileage may vary. 4.2BSD VAX, Gould, and Sun-3 produce output: > count is 800, now 800 >Which brings me to the question: is this code non-portable, or do >three out of four compilers surveyed fail to correctly implement K&R? Three out of four compilers surveyed failed to correctly implement K&R. The bug is an easy one to commit in PCC. It was fixed some time ago (I think it was fixed in 4.3BSD). Try also f() { unsigned *a(); int b(); *a() %= b(); } and see whether the code generated is correct. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
16012_3045@uwovax.uwo.ca (Paul Gomme) (06/28/88)
In article <133@daitc.ARPA>, jkrueger@daitc.ARPA (Jonathan Krueger) writes: > Here's a question of portability and language standards that came up in > a real life program. According to K&R or ANSI, predict the output of > the following code: > > #define DEFCONST 1.05 > main() > { > int count = 800; > > printf("count is %d, ", count); > count *= DEFCONST; > printf("now %d\n", count); > } > > My prediction, based on K&R, was the output: > count is 800, now 839 > Indeed, the Pyramid 98x produces exactly this output. > But your mileage may vary. 4.2BSD VAX, Gould, and Sun-3 produce output: > count is 800, now 800 > Which brings me to the question: is this code non-portable, or do > three out of four compilers surveyed fail to correctly implement K&R? Just to stir things up a little, under VAX/VMS, I get an answer of 839; Turbo C gives an answer of 840!
david@geac.UUCP (David Haynes) (07/08/88)
In article <430@uwovax.uwo.ca> 16012_3045@uwovax.uwo.ca (Paul Gomme) writes: >In article <133@daitc.ARPA>, jkrueger@daitc.ARPA (Jonathan Krueger) writes: >> Here's a question of portability and language standards that came up in >> a real life program. According to K&R or ANSI, predict the output of >> the following code: >> >> #define DEFCONST 1.05 >> main() >> { >> int count = 800; >> >> printf("count is %d, ", count); >> count *= DEFCONST; >> printf("now %d\n", count); >> } >> >> My prediction, based on K&R, was the output: >> count is 800, now 839 >> Indeed, the Pyramid 98x produces exactly this output. >> But your mileage may vary. 4.2BSD VAX, Gould, and Sun-3 produce output: ^^^^^^^^^^ >> count is 800, now 800 I don't get this at all! I am running on a VAX 8650 under Ultrix 2.0. My results are: cc non-optimized count is 800, now 839 cc optimized count is 800, now 839 gcc non-optimized count is 800, now 839 gcc optimized count is 800, now 839 vcc non-optimized count is 800, now 839 vcc optimized count is 800, now 839 HOWEVER, my sun 3/50 under Sun O/S 3.2 gives the following: cc non-optimized count is 800, now 800 cc optimized count is 800, now 800 As mentioned in the original article. yechhh! >> Which brings me to the question: is this code non-portable, or do >> three out of four compilers surveyed fail to correctly implement K&R? > > Just to stir things up a little, under VAX/VMS, I get an answer >of 839; Turbo C gives an answer of 840! Now, if on the sun, I s/count *= DEFCONST/count = count * DEFCONST/ I get the following: cc non-optimized count is 800, now 840 cc optimized count is 800, now 840 This is even more interesting! -david-
rob@raksha.eng.ohio-state.edu (Rob Carriere) (07/08/88)
In article <133@daitc.ARPA>, jkrueger@daitc.ARPA (Jonathan Krueger) writes: > [...] predict the output of the following code: > #define DEFCONST 1.05 > main(){ > int count = 800; > printf("count is %d, ", count); > count *= DEFCONST; > printf("now %d\n", count); > } > My prediction, based on K&R, was the output: count is 800, now 839 K&R says that ``a*=b'' is eqv to ``a=a*b'' *except* that ``a'' is evaluated only once. Sounds like the type cast is not going to be done => 800 is right. I don't know about ANSI, I *hope* they changed this; it's horribly counterintuitive. Yes, I'm biased; this is what my favorite compiler (Mark Williams C) says. Rob Carriere
gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/09/88)
In article <374@accelerator.eng.ohio-state.edu> rob@raksha.eng.ohio-state.edu (Rob Carriere) writes: >K&R says that ``a*=b'' is eqv to ``a=a*b'' *except* that ``a'' is >evaluated only once. Yes. >Sounds like the type cast is not going to be done => 800 is right. I didn't see any cast operator. If you mean type conversion, one IS supposed to be done in order to evaluate a*b where a is an int and b is a double. Then the assignment to a should truncate the double expression value back to an int. The correct answer is 839 or 840, depending on how precise your floating-point architecture is. 800 is definitely incorrect.
rob@kaa.eng.ohio-state.edu (Rob Carriere) (07/10/88)
In article <8228@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <374@accelerator.eng.ohio-state.edu> rob@raksha.eng.ohio-state.edu >(Rob Carriere) writes: [...] >>Sounds like the type cast is not going to be done => 800 is right. >I didn't see any cast operator. If you mean type conversion, >one IS supposed to be done in order to evaluate a*b where a is >an int and b is a double. Then the assignment to a should >truncate the double expression value back to an int. Whoops. You didn't see it because it isn't there, I *did* mean conversion. However, the conversion rule says that a is to be converted to double; this seems to contradict the idea that a is to be computed *once*. Rob Carriere
jfc@athena.mit.edu (John F Carr) (07/12/88)
In article <376@accelerator.eng.ohio-state.edu> rob@kaa.eng.ohio-state.edu (Rob Carriere) writes: >Whoops. You didn't see it because it isn't there, I *did* mean >conversion. However, the conversion rule says that a is to be >converted to double; this seems to contradict the idea that a is to be >computed *once*. I thought the purpose of the definition was so that things like subscripts and function calls needed to compute the lhs would not be repeated: a[f(x++) + --y] += 43; has different results than a[f(x++) + --y] = a[f(x++) + --y] + 43; To make this consistent with the standard, distinguish between "evaluation" and the type conversions required in computation. John Carr "When they turn the pages of history, jfc@Athena.mit.edu When these days have passed long ago, Will they read of us with sadness For the seeds that we let grow?" --Neil Peart
chris@mimsy.UUCP (Chris Torek) (07/12/88)
In article <376@accelerator.eng.ohio-state.edu> rob@kaa.eng.ohio-state.edu (Rob Carriere) writes: [re int a; ... a *= 1.05;] >... the conversion rule says that a is to be converted to double; this >seems to contradict the idea that a is to be computed *once*. Right idea, wrong expansion: a's *address* (if it has one) is to be computed once. (a itself is indeed computed only once: if a is 800 it is computed/evaluated as 800. That value, now in a temporary somewhere, is converted to double, multipled, and stored back in a's address.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guy@gorodish.Sun.COM (Guy Harris) (07/13/88)
> >> But your mileage may vary. 4.2BSD VAX, Gould, and Sun-3 produce output: > ^^^^^^^^^^ > >> count is 800, now 800 > > I don't get this at all! I am running on a VAX 8650 under Ultrix 2.0. So? He said "4.2BSD", not "Ultrix 2.0". 4.2BSD and Ultrix 2.0 are different systems; there's certainly no guarantee that any particular bugs in the 4.2BSD compiler are also in the Ultrix 2.0 compiler. One would hope, in fact, that this would *not* be the case.... I see no reason not to take him at his word here; I presume that he, at least, is actually *running* 4.2BSD. > HOWEVER, my sun 3/50 under Sun O/S 3.2 gives the following: > > cc non-optimized count is 800, now 800 > cc optimized count is 800, now 800 I believe this is an old PCC bug; the 4.2BSD VAX and Sun compilers are PCC-based, and the Gould one may be PCC-based as well. I would not be surprised if the Pyramid compiler were *not* PCC-based. My Sun-4/260, and a Sun-3/180 nearby, both running SunOS 4.0, as well as a not-so-nearby Sun386i running SunOS 4.0RRBETA2, all give cc non-optimized count is 800, now 840 cc optimized count is 800, now 840 A 4.3BSD VAX gives cc non-optimized count is 800, now 839 cc optimized count is 800, now 839 Presumably the DEC compiler (if it's not the VAX C compiler, in which case you should get the same results as on VAX/VMS) has had this bug fixed, as have the 4.3BSD compiler and the SunOS compilers.
phil@osiris.UUCP (Philip Kos) (07/20/88)
In article <59649@sun.uucp>, guy@gorodish.Sun.COM (Guy Harris) writes: > I would not be surprised if the Pyramid compiler were *not* PCC-based. You're right. When we got our first Pyramid system here at JHH (January, 1985), OSx cc was was pretty much just vanilla PCC. This changed in about mid-1985 as I recall. Does anyone from Pyramid (Carl? Sylvan? Eric?) want to confirm the date for me? Phil Kos A Pretty Happy Pyramid (and soon Sun) User
ihm@nrcvax.UUCP (Ian H. Merritt) (07/29/88)
david@geac.UUCP (David Haynes) says: . . . >>> Which brings me to the question: is this code non-portable, or do >>> three out of four compilers surveyed fail to correctly implement K&R? >> >> Just to stir things up a little, under VAX/VMS, I get an answer >>of 839; Turbo C gives an answer of 840! > > >Now, if on the sun, I s/count *= DEFCONST/count = count * DEFCONST/ >I get the following: > >cc non-optimized count is 800, now 840 >cc optimized count is 800, now 840 > Microsoft C also produces the 840 result, suggesting that it's indeed a rounding issue whether you get 839 or 840, but from the above substitution, it sure looks like the sun compiler has a bug. Let's see now, compiled on my sun (SunOS 3.5 standard distribution), I get: cc non-optimized count is 800, now 840 cc optimized count is 800, now 840 Funny thing, but it's not happening here... I wonder when this was fixed... Incidentally, I got the same results on an IS68K bsd unix running very old software... -i
gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/29/88)
In article <376@accelerator.eng.ohio-state.edu> rob@kaa.eng.ohio-state.edu (Rob Carriere) writes: >However, the conversion rule says that a is to be >converted to double; this seems to contradict the idea that a is to be >computed *once*. That's not the rule. a op= b (where a and b are expressions) is equivalent to a = a op b EXCEPT that the expression a is EVALUATED only once. I.e. if evaluation of the expression a has side-effects, they will occur only once. Once the expression is evaluated, it is used in the context a = a op b and other stuff happens at that point.