----- Original Message -----
From: "Brian Baquiran" <[EMAIL PROTECTED]>
To: "Philippine Linux Users Group Mailing List" <[EMAIL PROTECTED]>
Sent: Thursday, July 10, 2003 9:40 AM
Subject: Re: [plug] [OT] i++ and ++i


> Anuerin G. Diaz wrote:
> > On Wed, 11 Jun 2003 20:49:49 +0800,  "fooler" <[EMAIL PROTECTED]>
wrote:
> >>here are some more side effects of order of evaluation:
> >>
> >>f() + g()
> >>
> >>a[i] = i++;
> >>
> >>f(x++, x++, x++)
> >>
> >   i know this is an expert list but would you care to explain further
what is the expected and actual (usually what comes out) of the examples you
have given above? thanks.
>
> That's exactly the point -- there's no definite or specified order in
which the
> expressions will be evaluated. The actual results will vary depending on
> compiler, optimization flags, alignment of the planets, and whether you're
> wearing clean underwear that day.

aside from brian's statement above, i would like also to add and worth
noting too that different machine architecture affects the order of
evaluation also :->

----- Original Message -----
From: "Pablo Manalastas" <[EMAIL PROTECTED]>
To: "fooler" <[EMAIL PROTECTED]>
Sent: Thursday, June 12, 2003 5:15 AM
Subject: Re: [plug] [OT] i++ and ++i


> Quoting fooler <[EMAIL PROTECTED]>:
>
> > it is ok doc im not confuse :-> this is a well known *side effect* of
*order
> > of evaluation* :-> the order of evaluation like the above is NOT
specified
> > by any C specification anywhere... therefore you will see side effects
or
> > unwanted results from different compilers :->
>
> The C standard is clear about order of evaluation: the additions indicated
> in the expression are left-associative operations, the prefix ++
> means increment before use (producing a side effect), and the postfix ++
> means use before incrementing (another side effect).

doc, i believe what you mean above is that, the C standard is clear about
the *precedence* and *level of hierachry* of its operators but C standard
did not specify any about the order of evaluation... one good example as
what i shown above is:

f() + g()

with this statement, some compilers will evaluate f first and then add g but
others will evaluate g first and then add f... therefore standard C
specification about order of evaluation is silent about it :->

>The question is why the
> value is 7 and not 8?

that is a good question doc :-> i will show that below why is 7 but first of
all, i would like to ask an apology from you that i post your private email
here in plug because i believe others will benefit this discussion for
educational purposes only :->

> So let me do the step-by-step analysis of the
> expression, again:
>
> Step     Side-effect        i = 0;
> Number   on i after         i = i++ + ++i + i++ + ++i;
>          the increment
>
> 1         1                     0
> 2         2                     0   +   2
> 3         3                     0   +   2  + 2
> 4         4                     0   +   2  + 2  +   4    -> 8
>
> After the last increment, i has the value 4, but then the additions
> are done left-associative using temporaries (integer registers?)
> for the intermediate results, and the final result of 8 is assigned
> to i, overwriting the 4.
>
> Why gcc gives the value 7 for i is not clear to me.

the exact answer should be 8 if you evaluate it from left to right but due
to machine architecture, compiler designs, optimizations, etc as what brian
pointed out, the result varies... 7 for GCC, 10 for borland C, etc..

but let us stick to GCC and how GCC evaluate it...

instead of:

i = 0;
i = i++ + ++i + i++ + i++;

let us simplify first and ill give you such a good example as shown below:

i = 0;
i = i++ + ++i;

if you manually interpret as what you did above, the answer must be 2 but
GCC result to 3... why? :->

what GCC did is that, it evaluate ++i first, then add to i++ then increment
it...

now to prove my statement above, the best thing to do is to read the machine
code that gcc created it... so here it is:

i = 0;
    movl $0x0, 0xfffffffc(%ebp)
i = i++ + ++i;
    lea 0xfffffffc(%ebp), %eax
    incl (%eax)
    mov 0xfffffffc(%ebp), %edx
    lea 0xfffffffc(%ebp), %eax
    add %edx, (%eax)
    lea 0xfffffffc(%ebp), %eax
    incl (%eax)

ill simplify further the above machine codes for readability purposes

 i = 0;
    mov 0, i
 i = i++ + ++i;
    lea i, ax
    inc i
    mov i, dx
    lea i, ax
    add dx, i
    lea i, ax
    inc i

ok ill explain it line by line

i = 0
    mov 0, i

this is a self explanatory that the value 0 is move to i variable

 i = i++ + ++i;
    lea i, ax
    inc i

the above two machine language evaluates the ++i first instead of i++
because you will see there that the code directly manipulate the variable i
in the memory than assign it to a temporary register which is suppose to be
for i++... gcc put a higher precedence to ++i than i++... that is why gcc
evaluates ++i first than i++ :->

    mov i, dx

the line above evaluates i++ which move to a temporary register which is DX

    lea i, ax
    add dx, i

the lines above add i++ and ++i already

    lea i, ax
    inc i

then increment i as what i++ said for late increment

again... gcc evaluates ++i first because it has a higher precedence than
i++... this is what the way i interpret gcc.. you shall see later on why i =
i++ + ++i + i++ + ++i is equal to 7


gcc generated machine code for i = i++ + ++i + i++ + ++i

i = 0;
    movl $0x0, 0xfffffffc(%ebp)
i = i++ + ++i + i++ + ++i;
    lea 0xfffffffc(%ebp), %eax
    incl (%eax)
    mov 0xfffffffc(%ebp), %eax
    mov %eax, %edx
    add 0xfffffffc(%ebp), %edx
    mov 0xfffffffc(%ebp), %eax
    add %eax, %edx
    lea 0xfffffffc(%ebp), %eax
    incl (%eax)
    lea 0xfffffffc(%ebp), %eax
    add %edx, (%eax)
    lea 0xfffffffc(%ebp), %eax
    incl (%eax)
    lea 0xfffffffc(%ebp), %eax
    incl (%eax)

to simplify things:

i = 0;
    mov 0, i
i = i++ + ++i + i++ + ++i;
    lea i, ax
    inc i
    mov i, ax
    mov ax, dx
    add i, dx
    mov i, ax
    add ax, dx
    lea i, ax
    inc i
    lea i, i
    add dx, i
    lea i, ax
    inc i
    lea i, ax
    inc i

here is how gcc evaluates it in simple term...

let A = i++
let B = ++i
let C = i++
let D = ++i

so that i = A + B + C + D

gcc will try to interpret A + B first as what the machine code tell us...

since B has a higher precedence than A, B will going to evaluate first

1) A + B
2)       1
3)  1
4)  1  + 1

at line 2, the value of variable i in memory is 1 because B altered it...
line 3 will try to read the value of A which is 1 due to B operation a while
ago... at line 4, the value 1 + 1 will be stored at temporary variable which
is register DX as what the machine code tell us... DX or A + B is now 2

now let X = A + B which is 2 and try to evaluate the next operand which is C

1) X + C
2)        1
3)  2
4)  2 + 1

still the variable i in memory is 1 but the temporary variable DX is already
3

now let Y = X + C which is 3 and try to evaluate the next operand which is D

1) Y + D
2)        2
3)  3
4)  3 + 2

now the variable i in memory is 2 because D altered it... since there is no
more to evaluate, the temporary variable which is DX will be added to
variable i in memory... after that, the value of i is now 5...

since A and C is i++, gcc will late increment it.. thus, it will increment
two times (as what you saw the last four lines of its machine code) and
thus... the final value of i is 7 :->

fooler.


--
Philippine Linux Users' Group (PLUG) Mailing List
[EMAIL PROTECTED] (#PLUG @ irc.free.net.ph)
Official Website: http://plug.linux.org.ph
Searchable Archives: http://marc.free.net.ph
.
To leave, go to http://lists.q-linux.com/mailman/listinfo/plug
.
Are you a Linux newbie? To join the newbie list, go to
http://lists.q-linux.com/mailman/listinfo/ph-linux-newbie

Reply via email to