Re: Function call evaluation order
- From: "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@xxxxxxxxxxxxxxx>
- Date: Fri, 24 Mar 2006 10:06:31 -0800
"Frederico Pissarra" <frederico@xxxxxxxxxxx> wrote in message
news:ujwJxd2TGHA.1868@xxxxxxxxxxxxxxxxxxxxxxx
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@xxxxxxxxxxxxxxx>
escreveu na mensagem news:O1z0A71TGHA.4740@xxxxxxxxxxxxxxxxxxxxxxx
Here's an even better one:
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
template <class T>
T inc(T& i)
{
T t = i;
++i;
return t;
}
void f1()
{
char* data[] = { "one ", "two ", "three " };
int i = 0;
string s;
s.assign(data[i++]).append(data[i++]).append(data[i++]);
cout << s << endl;
}
void f2()
{
char* data[] = { "one ", "two ", "three " };
int i = 0;
string s;
s.assign(data[inc(i)]).append(data[inc(i)]).append(data[inc(i)]);
cout << s << endl;
}
void f3()
{
char* data[] = { "one ", "two ", "three " };
int i = 0;
string s;
s.assign(data[i++]);
s.append(data[i++]);
s.append(data[i++]);
cout << s << endl;
}
int main()
{
f1();
f2();
f3();
}
compiled with or without optimization, with VC8 or VC7.1 outputs
one one one
three two one
one two three
If precendence alone were enough, all three lines would be the same.
Undefined behavior in action! Only f3 has well-defined behavior - it
must produce "one two three " according to the C++ standard. f2 has
partially defined behavior as the only valid outputs from it consist of
the strings "one ", "two " and "three " once each in some undefined
order. f1 has.completely undefined behavior since i is modified twice
between sequence points.
-cd
The behavior described can be explained easily with operator precedence:
Note that [] has higher precedence than () - funcion call. So 3
post-increments will be performed AFTER the whole expression is evaluated.
That's why "one one one" is the result... Is almost like if f1() is the
same thing as f3().
I'm sorry, but that's not right.
Try this (really - try it). If you put the bodies of f1, f2 and f3 all
inline in main, then the results of f1 vary depending on whether f2 is
included or not (i.e. commenting out f2 causes f1 to produce a different
result). The results vary because the compile is not constrained to produce
any particualr behavior for f1, and is constrained to produce one of 6
different results for f2. Only f3 has well-defined behavior.
In f2() the template function inc() will calculate the values and put them
on stack (anonymous object)... since [] has higher precedence! That's why
the inverse order occurs...
Not so. use of the inc() function guarantees that i is incremented three
times but does not guarantee the relative order of the three occurrences of
data[inc(i)]. The code in f2() could have just as easily produced "one two
three " or even "two three one ". All would be legal results according to
the c++ standard.
Looking another way: [] has higher precedence than (), but inside the
data[] we have funcion calls that must be evaluated... so, all "inc(i)"
are evaluated before anything...
Maybe, but the the compiler isn't required to do it. Precedence absolutely
does NOT define total ordering of operations. Please re-read the eariler
messages in this thread - you're simply overlooking possibilities that are
allowed by the C++ standard (which defines what is and is not undefined
behavior).
f3() uses simple calls...
The same to the function calls... they are always called in order from
left to right because "." has higher precedence then [] or ().
Yes, in f1 and f2 the functions are called left to right - they must be due
to precedence. However, their arguments may be evaluated in any order -
left to right, right to left, or even interleaved (which is what happens
with f1).
In this particular example there is no undefined behavior!
In f3 there is no undefined behavior, but f2 and f1 both have undefined
behavior.
I'd suggest that you get a copy of the C++ standard and read up on sequence
points and undefined behavior. You're missing the concept entirely.
-cd
.
- Follow-Ups:
- Re: Function call evaluation order
- From: Igor Tandetnik
- Re: Function call evaluation order
- References:
- Function call evaluation order
- From: Cheng
- Re: Function call evaluation order
- From: Frederico Pissarra
- Re: Function call evaluation order
- From: Carl Daniel [VC++ MVP]
- Re: Function call evaluation order
- From: Frederico Pissarra
- Re: Function call evaluation order
- From: Carl Daniel [VC++ MVP]
- Re: Function call evaluation order
- From: Frederico Pissarra
- Re: Function call evaluation order
- From: Carl Daniel [VC++ MVP]
- Re: Function call evaluation order
- From: Carl Daniel [VC++ MVP]
- Re: Function call evaluation order
- From: Frederico Pissarra
- Function call evaluation order
- Prev by Date: Re: not a warning?
- Next by Date: Re: Function call evaluation order
- Previous by thread: Re: Function call evaluation order
- Next by thread: Re: Function call evaluation order
- Index(es):
Relevant Pages
|