++ operator: 4.2 vs 5.0
Author Message
++ 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
++ 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
++ 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

http://www.eskimo.com/~scs/C-faq/q3.3.html

--
Doug Harrison

Sat, 16 Oct 1999 03:00:00 GMT
++ operator: 4.2 vs 5.0

Fri, 19 Jun 1992 00:00:00 GMT
++ 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]
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
++ operator: 4.2 vs 5.0

Fri, 19 Jun 1992 00:00:00 GMT
++ 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

Jeff Nienaber

Quote:

> Read the C FAQ, section 3, in general, and question 3.3 to start, as

> http://www.eskimo.com/~scs/C-faq/q3.3.html

Sat, 16 Oct 1999 03:00:00 GMT
++ 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
++ operator: 4.2 vs 5.0

Fri, 19 Jun 1992 00:00:00 GMT
++ 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]
>         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
++ operator: 4.2 vs 5.0

Fri, 19 Jun 1992 00:00:00 GMT
++ 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
++ 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

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
++ 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.

foo = (a == 1) ? foo + 1 : 0

assuming, of course, that's what you really mean.

-Dave

Sun, 17 Oct 1999 03:00:00 GMT
++ 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

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

 Page 1 of 2 [ 15 post ]

Relevant Pages