ado@elsie.UUCP (04/12/84)
I compiled the following program with the 4.1bsd C compiler:
main()
{
int i;
i = 100;
i = i * .2;
printf("%d\n", i);
i = 100;
i *= .2;
printf("%d\n", i);
}
I got this output:
20
0
Is this a bug?
--
UUCP: decvax!harpo!seismo!rlgvax!cvl!elsie!ado
DDD: (301) 496-5688
peters@cubsvax.UUCP (04/15/84)
Looks like you found a real bug! on the 4.1bsd compiler, the following
program -- which compares i = i / f with i /= f -- gives the results indicated.
Obviously, the problem is that when the compiler encounters
"int op= float;" it casts the float to an int before doing the evaluation,
instead of promoting the int to a float, then casting the result.
According to K&R, p191, the two expressions "may be taken as equivalent"
(slight paraphrase), which is *very* misleading if this isn't a bug. They
then say, "... however, [for "op=" ] E1 [left-hand side] is evaluated only
once." This is opaque to me. Can someone explain it? I. e., does that
mean it's not a bug? It's egregious [look it up!] in any case.
main()
{
int i;
i = 100;
i = i / 3.3;
printf("i = i/3.3 gives: %d\n", i); /* gives 30, as expected */
i = 100;
i /= 3.3;
printf("i /= 3.3 gives: %d\n", i); /* gives 33!!!! */
}
{philabs,cmcl2!rocky2}!cubsvax!peters Peter S. Shenkin
Dept of Biol. Sci.; Columbia Univ.; New York, N. Y. 10027; 212-280-5517
"In accordance with the recent proclivity for clever mottos, this is mine."
smq@hlhop.UUCP (Steven M. Queriolo) (04/16/84)
I tried both i=100; i *= .2; and i=100; i /= 3.3; on our Unix System V (Release 2.0) and both of these 'bugs' produced the correct answers. -- Steven M. Queriolo AT&T Bell Laboratories ..........hlhop!smq
hansen@pegasus.UUCP (04/16/84)
I waited a couple of days before following up on this question to see if anyone else posted a reply. None has so far that I've seen, so here goes. The reported problem: integer *= float is not the same as integer = integer * float This is indeed a definite bug which has been around for many a moon. (It has been fixed in the System V compiler.) Dennis Ritchie himself commented on this very same problem in this very same forum last fall, acknowledging that it was a bug. Fix those compilers! Tony Hansen pegasus!hansen
crp@ccivax.UUCP (Chuck Privitera) (04/18/84)
The bug was reported (and fixed) back in January by randvax!edhall. I have installed the fix here and have not had any problems since. The fix follows: >From ritcv!rochester!seismo!hao!hplabs!sdcrdcf!randvax!edhall Wed Jan 11 03:13:26 1984 Subject: integer op= floating evaluated incorrectly by C compiler Newsgroups: net.bugs.4bsd,net.bugs.usg ------------------------------------ This bug may affect all pre-5.0USG C compilers, and perhaps earlier 5.0USG compilers as well. The below fix only works for PCC-derived compilers (such as the BSD VAX C compiler). Index: usr.lib/ccom 4.2BSD 4.1BSD 3.0USG Description: When assignement operators such as *= are used with an integer Left-Hand Side and a floating-point expression on the Right- Hand Side, results are incorrect. For example: int i = 6; i *= .5; leaves a value of 0 in i, rather than 3. The +=, -=, and /= operators are similarly affected. Caused by: Conversion of RHS of assignment to type of LHS before application of the operator. Fixed by: The fix is in two parts. First, the automatic forcing of type conversion to the LHS of an assignment op must be shut off in appropriate circumstances. This requires a change to tymatch() in mip/trees.c: 1031c1031,1035 < if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); --- > if( o==CAST || (t != t2 > && ( (dope[o]&(FLOFLG|ASGOPFLG)) != (FLOFLG|ASGOPFLG) > || t != INT || (t2 != DOUBLE && t2 != FLOAT) )) ) { > p->in.right = makety( p->in.right, tu, 0, (int)tu ); > } This causes certain assignment ops (+=, -=, *=, /=, i.e. the ones appropriate in floating-point) to remain in the parse tree without `balanced' operand types. When these get to code-generation the compiler would break unless the template table had the proper pieces added to it. Thus, in pcc/table.c: 712a713,729 > > /* begin new stuff */ > > ASG OPFLOAT, INAREG|FOREFF|FORCC, > SAREG|AWD, TWORD|TCHAR|TSHORT, > SAREG|AWD, TDOUBLE, > NAREG, RLEFT|RESCC, > " cvtZLd AL,A1\n OD2 AR,A1\n cvtdZL A1,AL\n", > > ASG OPFLOAT, INAREG|FOREFF|FORCC, > SAREG|AWD, TWORD|TCHAR|TSHORT, > SAREG|AWD, TFLOAT, > NAREG, RLEFT|RESCC, > " cvtZLf AL,A1\n OF2 AR,A1\n cvtfZL A1,AL\n", > > /* end new stuff */ > -Ed Hall Rand Corporation Santa Monica, CA decvax!randvax!edhall (UUCP) edhall@rand-unix (ARPA) There are plenty of parenthesis to miss there. Be careful! Chuck
allan@qtlon.UUCP (04/24/84)
<no, no, no. Please don't eat me> This is the same on 4.2bsd also. I Thought I would try it on our C compiler on our Prime and the results were 19 19 So it is sort of better, with floats the result was 19.999996 so it was almost 20. -- UUCP: {decvax,cbosgd,vax135}!qusavx!qtlon!allan ukc!qtlon!allan Phone: +44 1 637 7061
chris@basser.SUN (Chris Maltby) (04/26/84)
>This is the same on 4.2bsd also. I Thought I would try it on our C >compiler on our Prime and the results were >19 >19 >So it is sort of better, with floats the result was 19.999996 so it was >almost 20. Everyone knows that floating point units on PR1ME machines are up the sh*t. If anyone would like proof of this, I can send you a nice program to run. Chris Maltby University of Sydney