brianh@hpcvia.CV.HP.COM (brian_helterline) (07/27/90)
>Hi everyone. Here's one. I hope it is not as simple as my last one, >you remember( gets() ). I'm running the following program, and I'm not >getting out what I think I should be( so what else is new!). Any ideas? >#include <stdio.h> >main() >{ >int i= 0; >printf("\n%d %d\n", ++i, ++i); /* output is: 2 1, I expected 1 2 */ >i= 0; >printf("%d %d\n", ++i, i++); /* output is: 2 0, I expected 1 1 */ >i= 0; >printf("%d %d\n", i++, ++i); /* output is: 1 1, I expected 0 2 */ >i= 0; >printf("%d %d\n", i++, i++); /* output is: 1 0, I expected 0 1 */ >} > >Please send e-mail: ndimas@pikes.denver.colorado.edu > > > Thank You > Nicholas Dimas >---------- The output you got should is correct. The arguments to printf() [or any function] are pushed on to the stack right to left so they are in the correct order for printf() to pop them off when needed. If you evaluate each expression above right-to-left, you will "expect" exactly what the output was. Also note that each argument to printf() is a single expression, so once it is evaluated, the ++ operator can do the increment and then move on to the next expression. As an example, printf( "%d %d\n", i++, ++i ); arg1 = "%d %d\n" arg2 = i++; arg3 = ++i; if i=0 to start, and we evaluate right-to-left, arg3 = 1 and i = 1 arg2 = 1 and _then i = 2 arg1 = "%d %d\n"; I am not certain as to what ANSI specifies about whether this behavior is correct or not. I am just trying to describe what is happening. It is usually a bad idea to use ++ operators on the same variable more than once in _ANY_ expression. Hope this helps,
steve@taumet.com (Stephen Clamage) (07/29/90)
brianh@hpcvia.CV.HP.COM (brian_helterline) writes: |>printf("\n%d %d\n", ++i, ++i); |> etc | The output you got should is correct. The arguments to | printf() [or any function] are pushed on to the stack | right to left so they are in the correct order for | printf() to pop them off when needed. If you evaluate | each expression above right-to-left, you will "expect" | exactly what the output was. There is no guarantee in what order ++i and i++ will be evaluated, nor whether the incremented values will be stored before or after the second of the two is evaluated. Consequently, there is no way to predict what the output will be. The ANSI C standard explicitly says that you cannot count on when the "side effects" will take place, except that they will be complete before the function is called. C texts warn (or should warn) about modifying a variable which is referenced more than once in the same expression. Such code is often not warned-about by compilers, and may produce surprisingly different results on different systems. -- Steve Clamage, TauMetric Corp, steve@taumet.com
jc@atcmp.nl (Jan Christiaan van Winkel) (07/30/90)
From article <359@taumet.com>, by steve@taumet.com (Stephen Clamage): > brianh@hpcvia.CV.HP.COM (brian_helterline) writes: > > |>printf("\n%d %d\n", ++i, ++i); > |> etc > Such code is often not warned-about by compilers, and may produce > surprisingly different results on different systems. Lint's usefulness is too often underestimated. Whenever a program does not produce the results I expect, the first thing I'll do is use lint. I cannot stress this enough! USE LINT cat tst.c main() { int i; i=5; (void)printf("\n%d %d\n",++i, ++i); return 0; } lint tst.c tst.c ============== (6) warning: i evaluation order undefined JC -- Jan Christiaan van Winkel Tel: +31 80 566880 jc@atcmp.nl AT Computing P.O. Box 1428 6501 BK Nijmegen The Netherlands
tomr@ashtate (Tom Rombouts) (08/01/90)
In article <359@taumet.com> steve@taumet.com (Stephen Clamage) writes: >brianh@hpcvia.CV.HP.COM (brian_helterline) writes: > >|>printf("\n%d %d\n", ++i, ++i); > >There is no guarantee in what order ++i and i++ will be evaluated, Just to tie this into the recent "value of lint" thread, this is exactly the type of thing that a good lint will flag. ("Warning: expression depends on order of evaluation", etc.) Readers of this group may remember a "bug" fragment of code from MSC 5.1 to 6.0 that seemed to operate differently a few months ago that Gimpel PC-Lint correctly flagged. Tom Rombouts Torrance Techie tomr@ashtate.A-T.com V:(213) 538-7108
scs@adam.mit.edu (Steve Summit) (08/02/90)
In article <31530012@hpcvia.CV.HP.COM> brianh@hpcvia.CV.HP.COM (brian_helterline) writes: (in response to a code fragment like printf("%d %d\n", i++, i++);) > The arguments to > printf() [or any function] are pushed on to the stack > right to left so they are in the correct order for > printf() to pop them off when needed. Though correct for many machines, this is not true in general, for the C language neither mandates stack direction nor the existence of a stack. When you hear that evaluation order, and hence the behavior of an expression containing multiple side effects, is "undefined," it means that you cannot predict and should not know how various machines will do it, and that different machines may do it differently. To quote our good friends K&R, "Naturally, it is necessary to know what things to avoid, but if you don't know _how_ they are done on various machines, that innocence may help to protect you." > I am not certain as to what ANSI specifies about whether this > behavior is correct or not. ANSI C reaffirms that evaluation order in such cases is undefined, and furthermore (so I have been told) gives compilers license to reject programs depending on undefined evaluation order at compile time, without even flipping a coin and picking an order. > It is usually a bad idea to use ++ operators > on the same variable more than once in _ANY_ expression. Correct, except that the operative adverb is "always." See the frequently asked questions list for a bit more on this topic. Steve Summit scs@adam.mit.edu