Re: Function call evaluation order




"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@xxxxxxxxxxxxxxx>
wrote in message news:uLkXMTrTGHA.5808@xxxxxxxxxxxxxxxxxxxxxxx
"Frederico Pissarra" <frederico@xxxxxxxxxxx> wrote in message
news:%23yG0LLrTGHA.1204@xxxxxxxxxxxxxxxxxxxxxxx

"Cheng" <chengwuchew@xxxxxxxxxxx> escreveu na mensagem
news:u8X%23alhTGHA.4340@xxxxxxxxxxxxxxxxxxxxxxx

Hi folks,

I need help to explain the behavior with the code below. I would like
to chain up function call into a single line, while the order of the
function call is correct, I cannot be certain with order the expression
within the function call is evaluated.

Woud it be better, then, to write all the function call into seperate
lines?

With regards,
Cheng Wu


Code:

#include <stdio.h>
#include <string>

using namespace std;

void main()
{
char* data[] = {" zero ", " one ", " two ", " three "};
string s;
int i;

i = 0;
s.assign(data[i++]).append(data[i++]).append(data[i++]);
printf("%s\n", s.c_str());

i = 0;
s.assign(data[++i]).append(data[++i]).append(data[++i]);
printf("%s\n", s.c_str());

i = 0;
s.assign(data[i++]);
s.append(data[i++]);
s.append(data[i++]);
printf("%s\n", s.c_str());
}


Output:

zero zero zero
three three three
zero one two


It seems obvious to me that assign() will be performed before the first
append(), and this one before the second one. Obvious because member
selecion operator "." has the higher precedence and it's evaluated left
to right.

At the same time, in the first s.assign()... the routine uses
post-increment operators, so "i" will be incremented AFTER the expression
is evaluated. The same happens in the second s.assing().... but with
pre-increment.

The last sentences are evaluated separately, so "s.assing(data[i++])" is
the same as "s.assign(data[i]); i++;".

Take a look at the precedence table in any good C book (or MSDN)...
you'll notice that . has the higher precedence... followed by ->,
followed by [], followed by funcion call "()"...

Hope it helped!

But precedence does not fully determine the execution order. A valid
order for the original expression is:

evaluate data[i] ; argument to last append
increment i
evaluate data[i] ; argument to first append
increment i
evaluate data[i] ; argument to assign
increment i
call assign ; sequence point
call append ; sequence point
call append ; sequence point

Another valid order is:

evaluate data[i] ; argument to assign
increment i
call assign ; sequence point
evaluate data[i] ; argument to first append
increment i
call append ; sequence point
evaluate data[i] ; argument to second append
increment i
call append ; sequence point

Note that this results in the reversal of the operands to the three
functions.

Another legal order is:

evaluate data[i] ; argument to last append
evaluate data[i] ; argument to first append
evaluate data[i] ; argument to assign
increment i
increment i
increment i
call assign ; sequence point
call append ; sequence point
call append ; sequence point

Note that this results in all three calls being made with the same
arguments.

An example of an invalid ordering:

evaluate data[i] ; argument to last append
evaluate data[i] ; argument to first append
evaluate data[i] ; argument to assign
call assign ; sequence point
call append ; sequence point
call append ; sequence point
increment i
increment i
increment i

This ordering is invalid because the side-effects of the evaluation of the
parameters for a function call are split across the function call.

The problem that precedence alone doesn't cover is that the relative order
of evaluation of the arguments of the three function calls is not defined,
nor is whether the evaluation of those arguments overlaps.

-cd



Still... In the last example I show to you, here is the assembly generated
by compiling without optimizations (cl -Od -FAs -Fa -c test.c) - of course
the code sintax is a little more complex than that... but it shows pos and
pre increment in action...

----------%<--------------%<---------------
_main proc
; i is a local var, allocated on stack
mov [i],0
mov eax,[i]
mov edx,eax

push eax
push edx
push offset szFmt
call _printf ; printf("%d %d", i, i);
mov ecx,[i]
add ecx,1
mov [i],ecx ; i = i + 1;
mov edx,[i]
add edx,1
mov [i],edx ; i = i + 1;

mov eax,[i]
add eax,1
mov [i],eax ; i = i + 1;
mov ecx,[i]
add ecx,1
mov [i],ecx ; i = i + 1
push eax
push ecx
push offset szFmt
call _printf ; printf("%d %d", i, i);
ret
_main endp
----------%<--------------%<---------------

[]s
Fred


.



Relevant Pages

  • Re: Function call evaluation order
    ... append(), and this one before the second one. ... evaluate data; argument to first append ... This ordering is invalid because the side-effects of the evaluation of the ...
    (microsoft.public.vc.language)
  • Increment number in append query
    ... table(with a sequential job no). ... append query to try and increment the job no, ... for all subsequent records: Expr2: (Nz(DMax("JobNo","Job ...
    (microsoft.public.access.queries)
  • Re: Defining an access table via VBA (SQL DDL)
    ... You set the field attribute to dbAutoIncrField. ... If you want the auto numbers ... to be random rather than incremental, you append the field to the table, ... > newvalues to increment to create an autonumber field? ...
    (microsoft.public.word.vba.general)
  • Re: Ring Buffer Index
    ... To "increment" the index of the ring buffer, ... I wonder if the pre-increment is as undefined as the post increment .... ... MOV, R0 ... This saves two MOV operations (one register-register and one to ...
    (comp.lang.c)
  • Re: I am a complete novice in access help
    ... each time a page start (print page header), increment it in each detail ... push it in the appropriate control in the page footer. ...
    (microsoft.public.access.queries)

Loading