Author |
Message |
Jeff Nienabe #1 / 15
|
 ++ operator: 4.2 vs 5.0
Has anybody noticed that the ++ operator in the following example works differently in VC 5.0 than it did in VC 4.2?? int foo = 1; int a = 1; foo = (a == 1) ? foo++ : 0; What should the value of foo be after the above statement? In VC 4.2, the value is 2 (foo is incremented). In VC 5.0, the value is 1 (foo is not incremented). Any thoughts? Jeff Nienaber
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
Andy #2 / 15
|
 ++ operator: 4.2 vs 5.0
I would expect foo to be 1. If the statement were foo = (a == 1) ? ++foo : 0; I would expect it to be 2, maybe. Unfortunately I forget what this symptom is called in C 'speak', but, particularly the way you have it written, it is ambiguous.
Quote: > Has anybody noticed that the ++ operator in the following example works > differently in VC 5.0 than it did in VC 4.2?? > int foo = 1; > int a = 1; > foo = (a == 1) ? foo++ : 0; > What should the value of foo be after the above statement? > In VC 4.2, the value is 2 (foo is incremented). In VC 5.0, the value is 1 > (foo is not incremented). > Any thoughts? > Jeff Nienaber
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
Doug Harris #3 / 15
|
 ++ operator: 4.2 vs 5.0
On Tue, 29 Apr 1997 12:48:59 -0700, "Jeff Nienaber" Quote:
>Has anybody noticed that the ++ operator in the following example works >differently in VC 5.0 than it did in VC 4.2?? >int foo = 1; >int a = 1; >foo = (a == 1) ? foo++ : 0; >What should the value of foo be after the above statement? >In VC 4.2, the value is 2 (foo is incremented). In VC 5.0, the value is 1 >(foo is not incremented). >Any thoughts?
Read the C FAQ, section 3, in general, and question 3.3 to start, as it addresses exactly your example: http://www.eskimo.com/~scs/C-faq/q3.3.html -- Doug Harrison
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
#4 / 15
|
 ++ operator: 4.2 vs 5.0
|
Fri, 19 Jun 1992 00:00:00 GMT |
|
 |
Dennis Krabb #5 / 15
|
 ++ operator: 4.2 vs 5.0
I have additional information for Jeff's question. When producing assembler listings with the code Jeff provided they are quite different. VC++ 4.2b ---------------- ; int foo = 1; mov DWORD PTR _foo$[ebp], 1 ; int a = 1; mov DWORD PTR _a$[ebp], 1 ; foo = (a == 1) ? foo++ : 0; cmp DWORD PTR _a$[ebp], 1 jne $L463 inc DWORD PTR _foo$[ebp] jmp $L464 $L463: mov DWORD PTR _foo$[ebp], 0 $L464: (setup for printf code starts here) VC++ 5.0 -------------- ; int foo = 1; mov DWORD PTR _foo$[ebp], 1 ; int a = 1; mov DWORD PTR _a$[ebp], 1 ; foo = (a == 1) ? foo++ : 0; cmp DWORD PTR _a$[ebp], 1 jne SHORT $L473 mov eax, DWORD PTR _foo$[ebp] mov DWORD PTR -12+[ebp], eax mov ecx, DWORD PTR _foo$[ebp] add ecx, 1 mov DWORD PTR _foo$[ebp], ecx jmp SHORT $L474 $L473: mov DWORD PTR -12+[ebp], 0 $L474: mov edx, DWORD PTR -12+[ebp] mov DWORD PTR _foo$[ebp], edx The VC++ 4.2b assembly listing is more what I would expect to see from an assembler programming point of view as opposed to the VC++ 5.0 of using a temporary stack variable (-12+[ebp]) and the use of the assembler add statement, which must use a register. Dennis Krabbe
Quote: > Has anybody noticed that the ++ operator in the following example works > differently in VC 5.0 than it did in VC 4.2?? > int foo = 1; > int a = 1; > foo = (a == 1) ? foo++ : 0; > What should the value of foo be after the above statement? > In VC 4.2, the value is 2 (foo is incremented). In VC 5.0, the value is 1 > (foo is not incremented). > Any thoughts? > Jeff Nienaber
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
#6 / 15
|
 ++ operator: 4.2 vs 5.0
|
Fri, 19 Jun 1992 00:00:00 GMT |
|
 |
Jeff Nienabe #7 / 15
|
 ++ operator: 4.2 vs 5.0
Although that section in the faq would seem to address this exactly, I should point out that the following code has the same result in 4.2 and 5.0: int foo = 1; foo = foo++; In this example, foo ends up being 2 in both 4.2 and 5.0. Adding the conditional part in my first example causes the 5.0 compiler to return 1 instead of 2. Jeff Nienaber
Quote:
> Read the C FAQ, section 3, in general, and question 3.3 to start, as > it addresses exactly your example: > http://www.eskimo.com/~scs/C-faq/q3.3.html
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
Jeff Nienabe #8 / 15
|
 ++ operator: 4.2 vs 5.0
I think I agree that it works correctly in 5.0. In any case, the use of ++ in my code example is ambiguous (as Andy W pointed out). It would be better to use ++foo, and best to use foo+1. Jeff Nienaber
Quote:
> We noticed it here pretty quickly - it broke a part of our UI. The general > consensus was that it post-incrementing behaves correctly in 5.0 (although > I'm not certain it was intentionally "fixed"). > Anyway, ++foo and foo+1 work as one would expect. Actually, the strongest > feedback here was that it would have been clearer to use if/else instead. > And a cursory study indicated that a release build (maximize speed, I > think) produced the same assembly code for both. (For what its worth, the > if/else version in a debug build appeared to be smaller and faster).
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
#9 / 15
|
 ++ operator: 4.2 vs 5.0
|
Fri, 19 Jun 1992 00:00:00 GMT |
|
 |
Ronald M. Marti #10 / 15
|
 ++ operator: 4.2 vs 5.0
Dennis, Regardless of the fact that the behavior here is undefined, I take your sample assembler output as indicative of the compiler as a whole. I know that the compiler was rewritten between 4.2 and 5.0 and I hope that the optimized code looks a lot better but, boy, <<is that ugly code>>! It gives me the shivers. If course, even if the optimized code looks wonderful, we don't dare use it, knowing that optimization unleashes the floating point gremlin in the compiler. Ron Martin Ann Arbor, MI Quote:
> I have additional information for Jeff's question. When producing > assembler listings with the code Jeff provided they are quite different. > VC++ 4.2b > ---------------- > ; int foo = 1; > mov DWORD PTR _foo$[ebp], 1 > ; int a = 1; > mov DWORD PTR _a$[ebp], 1 > ; foo = (a == 1) ? foo++ : 0; > cmp DWORD PTR _a$[ebp], 1 > jne $L463 > inc DWORD PTR _foo$[ebp] > jmp $L464 > $L463: > mov DWORD PTR _foo$[ebp], 0 > $L464: > (setup for printf code starts here) > VC++ 5.0 > -------------- > ; int foo = 1; > mov DWORD PTR _foo$[ebp], 1 > ; int a = 1; > mov DWORD PTR _a$[ebp], 1 > ; foo = (a == 1) ? foo++ : 0; > cmp DWORD PTR _a$[ebp], 1 > jne SHORT $L473 > mov eax, DWORD PTR _foo$[ebp] > mov DWORD PTR -12+[ebp], eax > mov ecx, DWORD PTR _foo$[ebp] > add ecx, 1 > mov DWORD PTR _foo$[ebp], ecx > jmp SHORT $L474 > $L473: > mov DWORD PTR -12+[ebp], 0 > $L474: > mov edx, DWORD PTR -12+[ebp] > mov DWORD PTR _foo$[ebp], edx > The VC++ 4.2b assembly listing is more what I would expect to see from an > assembler programming point of view as opposed to the VC++ 5.0 of using a > temporary stack variable (-12+[ebp]) and the use of the assembler add > statement, which must use a register. > Dennis Krabbe
> > Has anybody noticed that the ++ operator in the following example works > > differently in VC 5.0 than it did in VC 4.2?? > > int foo = 1; > > int a = 1; > > foo = (a == 1) ? foo++ : 0; > > What should the value of foo be after the above statement? > > In VC 4.2, the value is 2 (foo is incremented). In VC 5.0, the value is > 1 > > (foo is not incremented). > > Any thoughts? > > Jeff Nienaber
|
Sat, 16 Oct 1999 03:00:00 GMT |
|
 |
#11 / 15
|
 ++ operator: 4.2 vs 5.0
|
Fri, 19 Jun 1992 00:00:00 GMT |
|
 |
Doug Harris #12 / 15
|
 ++ operator: 4.2 vs 5.0
On 29 Apr 1997 23:19:43 GMT, "Steve Gruverman" Quote:
>We noticed it here pretty quickly - it broke a part of our UI. The general >consensus was that it post-incrementing behaves correctly in 5.0 (although >I'm not certain it was intentionally "fixed").
There is no correct behavior for: foo = foo++; That statement invokes undefined behavior. Quote: >Anyway, ++foo and foo+1 work as one would expect.
The statement: foo = ++foo; isn't any more correct than the above. It still invokes undefined behavior. However, foo = foo+1; is perfectly well-defined. It's all in the C FAQ... -- Doug Harrison
|
Sun, 17 Oct 1999 03:00:00 GMT |
|
 |
Doug Harris #13 / 15
|
 ++ operator: 4.2 vs 5.0
On Tue, 29 Apr 1997 17:31:25 -0700, "Jeff Nienaber" Quote:
>Although that section in the faq would seem to address this exactly, I >should point out that the following code has the same result in 4.2 and >5.0: >int foo = 1; >foo = foo++; >In this example, foo ends up being 2 in both 4.2 and 5.0. Adding the >conditional part in my first example causes the 5.0 compiler to return 1 >instead of 2.
It's still undefined. Don't rely on it. The conditional part is irrelevant, which is why the FAQ I cited exactly addresses your example. The conditional part may or may not alter the behavior you observe with those specific compiler releases, but there is no correct behavior, because the construct is undefined. That's the important part; empirical results don't matter at all in this context. But let's look at those results anyway. As you've discovered, you get different results depending on whether the ?: operator is involved. You cannot consider this a compiler bug, because the language specifies such constructs (i.e. modifying a variable twice between sequence points) as undefined. I think you've demonstrated nicely why you need to take this rule seriously. Besides the FAQ, also take a look at the Dec-96 C++ DWP, section 5, paragraph 4. -- Doug Harrison
|
Sun, 17 Oct 1999 03:00:00 GMT |
|
 |
Dave Schauman #14 / 15
|
 ++ operator: 4.2 vs 5.0
Quote: > Has anybody noticed that the ++ operator in the following example works > differently in VC 5.0 than it did in VC 4.2?? > int foo = 1; > int a = 1; > foo = (a == 1) ? foo++ : 0;
This is a classic C pitfall. First, let's get rid of the irrelevant bits. Your statement, as written, is really foo = foo++; The pitfall is that C allows two ways for this expression to be implemented: TEMP = foo; foo <- foo + 1 foo = TEMP /* with this implementation, foo will still be 1 after the statement */ or TEMP <- foo foo <- TEMP foo <- foo + 1 /* with this implementation, foo will be 2 after the statement */ To avoid this problem, just follow these two rules: 1. Know what operators cause side affects (e.g. operator ++(int) and operator =()) 2. Never, never, NEVER use two side-affecting operators on the same variable in the same expression. The order side affects occur within an expression in C and C++ is undefined. This uncertainty was allowed in the language because it allows compiler optimizers more opportunities to produce better code, and doesn't take away anything from the programmer. Try writing your code as foo = (a == 1) ? foo + 1 : 0 assuming, of course, that's what you really mean. -Dave
|
Sun, 17 Oct 1999 03:00:00 GMT |
|
 |
Ed Fult #15 / 15
|
 ++ operator: 4.2 vs 5.0
Quote: > The order side affects occur within an expression in C and C++ is > undefined.
What do you mean by "undefined"? Are you saying that the compiler does not know if the type is int, string, etc? If so, why? The parameter is defined in advance. Quote: > 2. Never, never, NEVER use two side-affecting operators on the same > variable > in the same expression.
What do you mean by this? -- Ed Fultz
Andover, Mass
|
Mon, 18 Oct 1999 03:00:00 GMT |
|
|
|