[comp.lang.c] DEFINITE bug in Turbo C 2.0

hendrik@zeusa.UUCP (Hendrik Vermooten) (03/22/90)

Here is a definite bug in C (discovered by Renier v. Wyk)

(Please, no speeches about not using ++a etc in a macro :-) I've never
 done it, and never plan to do it. Interesting bug, nonetheless)

#include <stdio.h>
#define SQR(a) a*a
main ()
{
	int a = 10, b = 10, x, y;

	x = SQR (++a);
	y = SQR (b++);
	printf ("%d\n", x);
	printf ("%d\n", y);
	a = 10;
	b = 10;
	printf ("%d\n", SQR (++a));
	printf ("%d\n", SQR (b++));
}

Run by Turbo C it gives:

144
100
132
110

And run by Microsoft C (under XENIX):

132
110
132
110

 *** ***     Hendrik Vermooten, ZEUS software
 * o o *     Bang: ..!uunet!ddsw1!olsa99!zeusa!hendrik
O|  I  |O    or hendrik@zeusa.UUCP
 | *** |
 \*****/

bad@pearl.sw.stratus.com (Bruce Dumes) (03/23/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>Here is a definite bug in C (discovered by Renier v. Wyk)
>
>Run by Turbo C it gives:
>
>144
>100
>132
>110
>
>And run by Microsoft C (under XENIX):
>
>132
>110
>132
>110
>

hey , interestingly enough, when I ran it on my sun 3/80 using cc I got:

132
100
132
100

when I put a semi-colon after the #include <stdio.h> and recompiled with
			cc I got:

132
100
132
110

and when I ran it on my sun compiled with gcc I got:

144
100
144
100

and when I ran it on a Stratus Computer with the Stratus C compiler I got:

132
110
132
110

which is the only version that agreed with Microsoft.  (If the versions were
voting I guess this one would win).

WHO'S GOT THE BUG?????



--
Bruce Dumes			|	"Massachusetts has the best 
bad@pearl.sw.stratus.com	|	 politicians money can buy"
Stratus Computer, Inc.

karl@haddock.ima.isc.com (Karl Heuer) (03/23/90)

In article <946@lectroid.sw.stratus.com> bad@pearl.sw.stratus.com (Bruce Dumes) writes:
>In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>>Here is a definite bug in C (discovered by Renier v. Wyk)
>>[Example of code which produces different results on two compilers, one of
>>them being inconsistent between two similar expressions in the same code]

This is not a compiler bug.  The order in which side-effects take place
between sequence points is unspecified, so both answers are "valid".

>[Several other compilers give still different results]
>WHO'S GOT THE BUG?????

The author of the code.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

dik@cwi.nl (Dik T. Winter) (03/23/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
 > Here is a definite bug in C (discovered by Renier v. Wyk)
 > 
 > (Please, no speeches about not using ++a etc in a macro :-) I've never
 >  done it, and never plan to do it. Interesting bug, nonetheless)
Right so, because it may lead to undefined behaviour.

But pray tell, what is the bug?

That undefined expressions give different results in different places?
That undefined expressions give different results with different compilers?

That is not a bug, that is a feature.
-- 
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

kenny@m.cs.uiuc.edu (03/23/90)

bad@pearl.sw.stratus.com writes:
>In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>>Here is a definite bug in C (discovered by Renier v. Wyk)
>>Run by Turbo C it gives:
		(one set of results)
>>And run by Microsoft C (under XENIX):
		(another set of results)
>hey , interestingly enough, when I ran it on my sun 3/80 using cc I got:
		(the same results as Turbo)
>when I put a semi-colon after the #include <stdio.h> and recompiled with
>			cc I got:
		(still another set of results)
>and when I ran it on my sun compiled with gcc I got:
		(good grief, another set of results)
>and when I ran it on a Stratus Computer with the Stratus C compiler I got:
		(the same results as Microsoft)
>WHO'S GOT THE BUG?????

The original test program.  You're depending on the value of

	(a++) * (a++)

One of the a's in this expression will show the unincremented value.
The other one may show the value incremented or unincremented,
according to the convenience of the compiler writer.

Kevin, KE9TV

steve@wattres.UUCP (Steve Watt) (03/23/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>Here is a definite bug in C (discovered by Renier v. Wyk)
>Run by Turbo C it gives:
>
>144
>100
>132
>110
>
>And run by Microsoft C (under XENIX):
>
>132
>110
>132
>110
>
Some more votes:
Microsoft C under SCO UNIX gives
132 110
132 110

AT&T C under SCO UNIX gives
132 110
132 110

cc under Ultrix gives
144 100
144 110 (?)

VAX C under Ultrix gives
144 110
144 110

cc on the DECStation gives
144 100
144 100

Interesting...
I would be inclined to agree with Microsoft's interpretation...
but I can sure understand most of the others, except for cc under Ultrix
giving different answers based on whether or not it's a function call.
-- 
Steve Watt
...!claris!wattres!steve		wattres!steve@claris.com also works
If you torture your data long enough, it'll eventually confess.

dks@shumv1.uucp (D. K. Smith) (03/23/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>Here is a definite bug in C (discovered by Renier v. Wyk)
>
>
>#include <stdio.h>
>#define SQR(a) a*a
>main ()
>{
>	int a = 10, b = 10, x, y;
>
>	x = SQR (++a);
>	y = SQR (b++);
>	printf ("%d\n", x);
>	printf ("%d\n", y);
>	a = 10;
>	b = 10;
>	printf ("%d\n", SQR (++a));
>	printf ("%d\n", SQR (b++));
>}
>


Hmmm...

THINK's "old" C compiler (version) 3.02 yields the following:

144
110
144
110


dk smith

reino@cs.eur.nl (Reino de Boer) (03/23/90)

karl@haddock.ima.isc.com (Karl Heuer) writes:

>>[Several other compilers give still different results]
>>WHO'S GOT THE BUG?????

>The author of the code.

I think the point made was not that the results should be the same, but
that the following code

#define f(a) a*a

int a, x;
a = 10;
x = f( ++a );

should either compute
r1 = ++a;
r2 = ++r1;
x = r1 * r2;
or
r2 = ++a;
r1 = ++r2;
x = r1 * r2;
in which case both computations leave (11 * 12) in "x".

Now, this all depends on the relative precedence of "++" and "*", and
that is all it should depend on.
To my knowledge the unary operators have priority below the primary
operators, but higher than any other binary operator.

Please correct me if I'm wrong, Reino

-- 
Reino R. A. de Boer     "We want to build the right product right, right?"
Erasmus University Rotterdam ( Informatica )
e-mail: reino@cs.eur.nl

dks@shumv1.uucp (D. K. Smith) (03/23/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>Here is a definite bug in C (discovered by Renier v. Wyk)
>
>#include <stdio.h>
>#define SQR(a) a*a
>main ()
>{
>	int a = 10, b = 10, x, y;
>
>	x = SQR (++a);
>	y = SQR (b++);
>	printf ("%d\n", x);
>	printf ("%d\n", y);
>	a = 10;
>	b = 10;
>	printf ("%d\n", SQR (++a));
>	printf ("%d\n", SQR (b++));
>}
>

Sorry about duplicating part of my previous post but I decided 
to compare the results of the above code on my THINK C 3.02 compiler
with the same code however using doubles (which in THINK C utilizes
the Motorola 68881 math coproc).

Integers yielded:
144
110
144
110


Using the following lines of code for replacements to the above lines...

double a = 10, b = 10, x, y;

fprintf (dfp, "%e\n", x);
fprintf (dfp, "%e\n", y);
fprintf (dfp, "%e\n", SQR (++a));
fprintf (dfp, "%e\n", SQR (b++));

This resulted in...
1.320000e+002
1.100000e+002
1.320000e+002
1.100000e+002


This is interesting but I cannot imagine the intent of the code
that led to this discovery.  What is a compiler to do?  That pre-incrmt
is a real nasty!


dk smith

tyler@procase.UUCP (William B. Tyler) (03/24/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
]Here is a definite bug in C (discovered by Renier v. Wyk)
]
]#include <stdio.h>
]#define SQR(a) a*a
]main ()
]{
]	int a = 10, b = 10, x, y;
]
]	x = SQR (++a);
]	y = SQR (b++);
]	printf ("%d\n", x);
]	printf ("%d\n", y);
]	a = 10;
]	b = 10;
]	printf ("%d\n", SQR (++a));
]	printf ("%d\n", SQR (b++));
]}
]
]Run by Turbo C it gives:
]
]144
]100
]132
]110
]
]And run by Microsoft C (under XENIX):
]
]132
]110
]132
]110

My reading of the ANSI standard implies that the order of 
storing the incremented results as compared to the order of
the other operations is not necessarily well-defined.  In
other words, this may not be an error.  Note that an implementation
is not required to evaluate similar expressions in the same
order in all circumstances.

I'd like to see some well-informed comment on this point.
-- 
Bill Tyler				...(tolerant|hpda)!procase!tyler

karl@haddock.ima.isc.com (Karl Heuer) (03/24/90)

In article <1990Mar23.073923.6425@cs.eur.nl> reino@cs.eur.nl (Reino de Boer) writes:
>Now, this all depends on the relative precedence of "++" and "*", and
>that is all it should depend on.  Please correct me if I'm wrong

You're wrong.  For example, another valid computation of "x = ++a * ++a" is
"r1 = a+1; r2 = a+1; x = r1*r2; ++a; ++a;".  The only constraint on the timing
of side effects is that they must take place after the previous sequence point
and before the next one.

The bottom line is: that code does not produce a well-defined result.  Don't
write code like that.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

scs@athena.mit.edu (Steve Summit) (03/24/90)

In article <451@wattres.UUCP> steve@wattres.UUCP (Steve Watt) writes:
>Some more votes:
...
>Interesting...
>...but I can sure understand most of the others, except for cc under Ultrix...

In article <1990Mar23.074526.8286@ncsuvx.ncsu.edu> dks@shumv1.ncsu.edu (D. K. Smith) writes:
>...I decided 
>to compare the results of the above code on my THINK C 3.02 compiler...

It has already been explained that the referenced code yields
undefined, compiler-dependent behavior.  Investigate it further
if you must, but please don't post the results here.  Which
"answer" a particular compiler gives is simply not useful (nor
particularly interesting).

In article <1990Mar23.073923.6425@cs.eur.nl> reino@cs.eur.nl (Reino de Boer) writes:
>I think the point made was not that the results should be the same, but
>that... both computations [should] leave (11 * 12) in "x".

Don't make the common mistake of believing that x++ increments x
just after yielding its former value, but before doing anything
else in the expression.  The incrementation merely happens later,
sometime before the following _statement_ is executed (formally,
before the next "sequence point"), but it need not happen before
the next use of x in the same expression.  (The "relative
precedence of '++' and '*'" doesn't really enter into it.)

                                            Steve Summit
                                            scs@adam.pika.mit.edu

jharkins@sagpd1.UUCP (Jim Harkins) (03/24/90)

In article <802@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>Here is a definite bug in C (discovered by Renier v. Wyk)
>	x = SQR (++a); printf("%d\n", a);
>	printf ("%d\n", SQR (++a));
>
>	(complains that that this prints different numbers)

Um, if I understand the phrase 'the evaluation order is undefined' correctly
then the only bug is the one you stepped on on the way to your desk.  I don't
see any reason for a compiler to treat these 2 cases the same.  Please be
a bit more careful before claiming a product has a DEFINATE bug in the future.


-- 
jim		jharkins@sagpd1

We are all aware of the high cost of alcohol abuse.  To help solve this problem
take this signature to your local liquor store for $1.00 off your next purchase.

gwyn@smoke.BRL.MIL (Doug Gwyn) (03/25/90)

In article <103@sail.procase.UUCP> tyler@procase.UUCP (William B. Tyler) writes:
>My reading of the ANSI standard implies that the order of 
>storing the incremented results as compared to the order of
>the other operations is not necessarily well-defined.  In
>other words, this may not be an error.  Note that an implementation
>is not required to evaluate similar expressions in the same
>order in all circumstances.

Yes, that's right.  Side effects may be deferred until a sequence point,
and explicit license is granted for assignment expressions in order to
permit maximal optimization.  Further, an implementation may randomly
decide how to handle each case and need not even do it the same way
for successive invocations of the very same code.  (Not that I really
expect an implementation to toss a coin, but it could be done.)

platt@ndla.UUCP (Daniel E. Platt) (03/25/90)

In article <802@zeusa.UUCP>, hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
> Here is a definite bug in C (discovered by Renier v. Wyk)
> 
> (Please, no speeches about not using ++a etc in a macro :-) I've never
>  done it, and never plan to do it. Interesting bug, nonetheless)

I'm not sure why you are calling this a bug...  You see, macro's are
evaluated by the C preprocessor.  The C Compiler never see's the macros.
There's a real reason WHY people say not to use ++ operations in a
macro.  Look at this below.

> 
> #include <stdio.h>
> #define SQR(a) a*a
> main ()
> {
> 	...
> 	x = SQR (++a);
> 	y = SQR (b++);
...
...	(print the results)
...

The way that the macro is evaluated looks like

	x = ++a * ++a;
	y = b++ * b++;

With ++'s being applied twice, you don't know whether ++ will be applied
RIGHT after the first evaluation or after the whole rhs of the equation
is handled.  The standards leave this undefined.  It is just assumed that
it will never be coded.  You CAN write macros that handle these correctly
by coding so that the argument is only used ONCE.

By the way, precedence is also a possible problem with this type of
situation.  For example, if you evaluated
	
	x = SQR(a + 1);

The preprocessor would generate

	x = a + 1 * a + 1;

Which wouldn't be at all what you intended (I don't think).  The macro
should have been declared:

#define SQR(x)  ((x) * (x))

> Run by Turbo C it gives:
...(one set of answers)
> And run by Microsoft C (under XENIX):
...(another set of answers)

As a last comment, I believe that the complaint about speeches using
a++ or ++a in macros was that Hendrik was expecting an answer like
"You shouldn't do that in a macro."  The answer I gave was to explain
what macros do, and then say something like "you shouldn't use expressions
like "x = a++ * a++."  And further that macros can HIDE this.  (This is
why everyone warns against using expressions with side effects as arguments
to macros.)  Hence my presumption of saying "You should be careful when
using expressions with side effects as arguments to macros."

Hope this helps...

Dan
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
||                                     1(914)945-1173            ||
||        Dan Platt                    1(914)941-2474            ||
||        Watson (IBM)                 PLATT@YKTVMV.BITNET       ||
||                           ..!uunet!bywater!scifi!ndla!platt   ||
||                                                               ||
||     The opinions expressed here do not necessarily reflect    ||
||                   those of my employer!                       ||
||                                                               ||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

grogers@convex.com (Geoffrey Rogers) (03/28/90)

In article <16269@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <1990Mar23.073923.6425@cs.eur.nl> reino@cs.eur.nl (Reino de Boer) writes:
>>Now, this all depends on the relative precedence of "++" and "*", and
>>that is all it should depend on.  Please correct me if I'm wrong
>
>You're wrong.  For example, another valid computation of "x = ++a * ++a" is
>"r1 = a+1; r2 = a+1; x = r1*r2; ++a; ++a;".  The only constraint on the timing
>of side effects is that they must take place after the previous sequence point
>and before the next one.
>
>The bottom line is: that code does not produce a well-defined result.  Don't
>write code like that.

I agree with Karl, it is not the compilers that are in error here, it is
the code. Also as a side note: x = ++a * ++a; is not ANSI C compliant.
The reason it is not, is because you are modifing the same object more then
once in the same expression.

cheers

+------------------------------------+---------------------------------+
| Geoffrey C. Rogers   		     | "Whose brain did you get?"      |
| grogers@convex.com                 | "Abbie Normal!"                 |
| {sun,uunet,uiucdcs}!convex!grogers |                                 |
+------------------------------------+---------------------------------+