 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Chris Jefferson Guest
|
Posted: Sun Jul 03, 2005 10:12 am Post subject: Undefined order of execution of function parameters |
|
|
Hello,
Out of curiousity, does anyone know why the order of execution of
function parameters is undefined?
(For those who aren't clear on what I mean, the following program
snippit can print either "fg" or "gf")
#include<iostream>
int f() { std::cout << "f"; return 0; }
int g() { std::cout << "g"; return 0; }
void function(int i, int j) {}
int main(void)
{ function(f(),g()); }
I assume it's just inherited from C, but I can't really see how it could
be benefical, and a couple of times I've wished the order was well defined.
Chris
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Sun Jul 03, 2005 10:24 pm Post subject: Re: Undefined order of execution of function parameters |
|
|
"Chris Jefferson" <caj (AT) cs (DOT) york.ac.uk> skrev i meddelandet
news:da66kr$rjj$1 (AT) pump1 (DOT) york.ac.uk...
| Quote: | Hello,
Out of curiousity, does anyone know why the order of execution of
function parameters is undefined?
|
It was left as a freedom to the compiler implementer, possibly leaving
some room for improved optimizations. Whether it really helps is often
debated.
| Quote: |
(For those who aren't clear on what I mean, the following program
snippit can print either "fg" or "gf")
#include
int f() { std::cout << "f"; return 0; }
int g() { std::cout << "g"; return 0; }
void function(int i, int j) {}
int main(void)
{ function(f(),g()); }
I assume it's just inherited from C, but I can't really see how it
could
be benefical, and a couple of times I've wished the order was well
defined.
|
On the other hand, if you really need a specific order, you just have to
state that explicitly:
int main()
{
const int i = f();
const int j = g();
function(i, j);
}
Bo Persson
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jack Klein Guest
|
Posted: Mon Jul 04, 2005 10:59 am Post subject: Re: Undefined order of execution of function parameters |
|
|
On 3 Jul 2005 06:12:43 -0400, Chris Jefferson <caj (AT) cs (DOT) york.ac.uk>
wrote in comp.lang.c++.moderated:
| Quote: | Hello,
Out of curiousity, does anyone know why the order of execution of
function parameters is undefined?
(For those who aren't clear on what I mean, the following program
snippit can print either "fg" or "gf")
#include
int f() { std::cout << "f"; return 0; }
int g() { std::cout << "g"; return 0; }
void function(int i, int j) {}
int main(void)
{ function(f(),g()); }
I assume it's just inherited from C, but I can't really see how it could
be benefical, and a couple of times I've wished the order was well defined.
Chris
|
The behavior is not undefined, which is a term with a very specific
meaning in both the C and C++ language standards. It is unspecified,
another term with a very specific meaning. It means that the
implementation must choose from a number of possibilities, and that it
is NOT required to document its choice.
As to why, it does have something to do with C, but not in the way you
are thinking.
C++ very carefully preserves the "spirit of C" wherever possible, and
one of the very first and most important principles of that spirit is
that "you don't pay for what you don't use".
By locking all compilers into doing *anything* in a specific way, you
are forcing some compilers to generate less efficient code at least
some of the time.
As you say, "a couple of times" you have wanted a particular order of
evaluation to be enforced. And many, many other times you did not
care at all.
In the small percentage of cases where a programmer needs a particular
order of evaluation, he/she can achieve it by splitting up expressions
into smaller expressions using multiple statements, or perhaps using a
variable or two to hold a temporary result. It is never impossible in
legal, valid code to get the necessary result.
Because C++ does not automatically do this for the small percentage of
cases, the large percentage of cases in every program do not pay the
price for less efficient code generation.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
chris jefferson Guest
|
Posted: Mon Jul 04, 2005 12:41 pm Post subject: Re: Undefined order of execution of function parameters |
|
|
Jack Klein wrote:
| Quote: | On 3 Jul 2005 06:12:43 -0400, Chris Jefferson <caj (AT) cs (DOT) york.ac.uk
wrote in comp.lang.c++.moderated:
Hello,
Out of curiousity, does anyone know why the order of execution of
function parameters is undefined?
(For those who aren't clear on what I mean, the following program
snippit can print either "fg" or "gf")
#include
int f() { std::cout << "f"; return 0; }
int g() { std::cout << "g"; return 0; }
void function(int i, int j) {}
int main(void)
{ function(f(),g()); }
I assume it's just inherited from C, but I can't really see how it could
be benefical, and a couple of times I've wished the order was well defined.
Chris
The behavior is not undefined, which is a term with a very specific
meaning in both the C and C++ language standards. It is unspecified,
another term with a very specific meaning. It means that the
implementation must choose from a number of possibilities, and that it
is NOT required to document its choice.
As to why, it does have something to do with C, but not in the way you
are thinking.
...
In the small percentage of cases where a programmer needs a particular
order of evaluation, he/she can achieve it by splitting up expressions
into smaller expressions using multiple statements, or perhaps using a
variable or two to hold a temporary result. It is never impossible in
legal, valid code to get the necessary result.
|
But of course if those temporary variables are vector
copying them around can be quite expensive.
| Quote: | Because C++ does not automatically do this for the small percentage of
cases, the large percentage of cases in every program do not pay the
price for less efficient code generation.
|
Can you give an example of how you can get more efficent code generation
by being able to do this reordering? It seems to me the only possible
way would be if you could inline both functions, but even then it seems
being able to reorder the order they are executed in isn't going to
bring any benefit...
Chris
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Mon Jul 04, 2005 5:43 pm Post subject: Re: Undefined order of execution of function parameters |
|
|
"chris jefferson" <caj (AT) cs (DOT) york.ac.uk> skrev i meddelandet
news:dab5qj$45h$1 (AT) pump1 (DOT) york.ac.uk...
| Quote: | Jack Klein wrote:
In the small percentage of cases where a programmer needs a
particular
order of evaluation, he/she can achieve it by splitting up
expressions
into smaller expressions using multiple statements, or perhaps using
a
variable or two to hold a temporary result. It is never impossible
in
legal, valid code to get the necessary result.
But of course if those temporary variables are vector<int>s or the
like,
copying them around can be quite expensive.
|
If performance is *that* important, perhaps you shouldn't pass
vector<int>s by value anyway? :-)
| Quote: |
Because C++ does not automatically do this for the small percentage
of
cases, the large percentage of cases in every program do not pay the
price for less efficient code generation.
Can you give an example of how you can get more efficent code
generation
by being able to do this reordering? It seems to me the only possible
way would be if you could inline both functions, but even then it
seems
being able to reorder the order they are executed in isn't going to
bring any benefit...
|
It just *might* depend on a lot of things, like the complexity of the
parameters, if there are common subexpressions, how values are passed to
the receiving function, how many registers are available, whatever.
It is not uncommon to push parameters on the stack in reverse order, at
least for functions with a variable number of parameters. That way the
first parameter is in a know place, at the top. Think printf("format",
....).
Will you require right-to-left evaluation for all functions? Even if the
machine doesn't have a stack?
What is the most effective order to evaluate
f(a + b + c + d + e + f + g + h, x, i + h + g + f + e + c + b + a)?
is it the same on all processors? Should we require one anyway?
By NOT restricting the order of the evaluation, the designers of the C
language left it up to the implementors to do the best they could.
Bo Persson
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
M Jared Finder Guest
|
Posted: Tue Jul 05, 2005 2:26 am Post subject: Re: Undefined order of execution of function parameters |
|
|
Bo Persson wrote:
| Quote: | "chris jefferson" <caj (AT) cs (DOT) york.ac.uk> skrev i meddelandet
news:dab5qj$45h$1 (AT) pump1 (DOT) york.ac.uk...
Jack Klein wrote:
Because C++ does not automatically do this for the small percentage
of
cases, the large percentage of cases in every program do not pay the
price for less efficient code generation.
Can you give an example of how you can get more efficent code
generation
by being able to do this reordering? It seems to me the only possible
way would be if you could inline both functions, but even then it
seems
being able to reorder the order they are executed in isn't going to
bring any benefit...
It just *might* depend on a lot of things, like the complexity of the
parameters, if there are common subexpressions, how values are passed to
the receiving function, how many registers are available, whatever.
It is not uncommon to push parameters on the stack in reverse order, at
least for functions with a variable number of parameters. That way the
first parameter is in a know place, at the top. Think printf("format",
...).
Will you require right-to-left evaluation for all functions? Even if the
machine doesn't have a stack?
What is the most effective order to evaluate
f(a + b + c + d + e + f + g + h, x, i + h + g + f + e + c + b + a)?
is it the same on all processors? Should we require one anyway?
|
If that + acts like the built in +, than it is irrelevant. All three
expressions have no side effects, so there is no noticeable order.
However, the compiler has no way to tell that this is the case for user
defined operator+ unless it is inlined.
My gut feeling is that most function parameter expressions have no side
effects -- they call only stateless functions. Defining an order of
evaluation here would only affect calls where a programmer assumed that
there was some order, most likely left to right. I think it would be
much better to make the order of evaluation well defined, automagically
fixing all these bugs instead of leaving it undefined. The potential
for optimization can be left in by providing a way to tell the compiler
which functions are stateless and which are statefull.
-- MJF
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Tue Jul 05, 2005 2:27 am Post subject: Re: Undefined order of execution of function parameters |
|
|
Bo Persson wrote:
| Quote: | By NOT restricting the order of the evaluation, the designers of the C
language left it up to the implementors to do the best they could.
|
And as has been much discussed here, I maintain that this is now a mistake.
It is unacceptable in C++ to have these order dependencies instead of a
well-defined order of evaluation . Arguments should be evaluated strictly
left-to-right, with each parameter of the called function initialized before
evaluation of the next expression begins. The simple fact that you cannot
call 'f(auto_ptr, auto_ptr)' as 'f(new, new)' without risk of memory leaks
is enough to prove that.
There is simply no justification for such gratuitous implementation-defined
behavior.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gabriel Dos Reis Guest
|
Posted: Tue Jul 05, 2005 10:54 am Post subject: Re: Undefined order of execution of function parameters |
|
|
Hyman Rosen <hyrosen (AT) mail (DOT) com> writes:
[...]
| Quote: | There is simply no justification for such gratuitous implementation-defined
behavior.
|
Is that a self-defining?
--
Gabriel Dos Reis
[email]gdr (AT) integrable-solutions (DOT) net[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Old Wolf Guest
|
Posted: Tue Jul 05, 2005 10:54 am Post subject: Re: Undefined order of execution of function parameters |
|
|
chris jefferson wrote:
| Quote: |
Can you give an example of how you can get more efficent code generation
by being able to do this reordering? It seems to me the only possible
way would be if you could inline both functions, but even then it seems
being able to reorder the order they are executed in isn't going to
bring any benefit...
|
Suppose the called function is expecting parameters in
right-to-left order (by far the most common way in practice).
For the sake of clarity let's assume there are no spare registers.
At the moment, the assembly generated for: f( a(), b(), c(), d() )
might look like:
call _d
push bc
call _c
push bc
call _b
push bc
call _a
push bc
call f
But if left-to-right order is enforced, the compiler would
have to write:
ld ix, SOME_ADDRESS
call _a
ld (ix+0),bc
call _b
ld (ix+2),bc
call _c
ld (ix+4),bc
call _d
push bc
push (ix+4)
push (ix+2)
push (ix+0)
call f
which is much more complicated.
Another example would be:
{
T value = foo();
f( a(), b(), c(value), d() );
}
In this example the compiler could call foo() and then call c()
immediately. But if left-right evaulation is forced, then the
compiler will have to store the value of 'value' somewhere while
it is calling a() and b() -- what a waste.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Jul 05, 2005 1:12 pm Post subject: Re: Undefined order of execution of function parameters |
|
|
In article <j5Kdnbsyj_-oVlTfRVn-2w (AT) speakeasy (DOT) net>, M Jared Finder
<jared (AT) hpalace (DOT) com> writes
| Quote: | If that + acts like the built in +, than it is irrelevant. All three
expressions have no side effects, so there is no noticeable order.
However, the compiler has no way to tell that this is the case for user
defined operator+ unless it is inlined.
My gut feeling is that most function parameter expressions have no side
effects -- they call only stateless functions. Defining an order of
evaluation here would only affect calls where a programmer assumed that
there was some order, most likely left to right. I think it would be
much better to make the order of evaluation well defined, automagically
fixing all these bugs instead of leaving it undefined. The potential
for optimization can be left in by providing a way to tell the compiler
which functions are stateless and which are statefull.
|
Please try to use the correct technical terms. Unspecified and undefined
have entirely different meanings in C++.
Now as any implementation is entitled to specify an order of evaluation
and can even document it (though that is not required for unspecified
behaviour) I have argued that requiring a specified order would no break
any existing program. However it would break many, if not all existing
implementations.
Does that matter? Well note how many people post problems with code they
have compiled with VC++ 6.0. That compiler is effectively ten years old
and pre-standard. My point? It isn't only code that has great longevity
but also implementations.
There is another issue, that of ABIs, unless all current ABIs specify
the same order for passing arguments, changing the current specification
would adversely affect some of them. That is a very, very big issue (Sun
Microsystems puts a provisional cost in invalidating its C++ ABI at one
billion dollars.) There maybe some hyperbole in that cost, but even so a
change would be very expensive (it would invalidate every shipped
library from every vendor supporting the ABI)
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Martin Bonner Guest
|
Posted: Tue Jul 05, 2005 1:13 pm Post subject: Re: Undefined order of execution of function parameters |
|
|
Hyman Rosen wrote:
| Quote: | Bo Persson wrote:
By NOT restricting the order of the evaluation, the designers of the C
language left it up to the implementors to do the best they could.
And as has been much discussed here, I maintain that this is now a mistake.
It is unacceptable in C++ to have these order dependencies instead of a
well-defined order of evaluation . Arguments should be evaluated strictly
left-to-right, with each parameter of the called function initialized before
evaluation of the next expression begins.
The simple fact that you cannot
call 'f(auto_ptr, auto_ptr)' as 'f(new, new)' without risk of memory leaks
is enough to prove that.
|
No it isn't. That should be fixed by requiring the compiler to
complete evaluatuating the expression for an argument before starting
on another argument. The order in which arguments are evalutated could
be left unspecified.
Note: I actually agree that order of evaluation should be much more
tightly specified by the standard. It's just that your evidence
doesn't prove as much as you claimed.
Can anyone provide any code where specifying an order of evaluation
prevents significant optimization opportunities AND the as-if rule
couldn't reasonably be used by the compiler to optimize anyway?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Tue Jul 05, 2005 5:50 pm Post subject: Re: Undefined order of execution of function parameters |
|
|
Francis Glassborow wrote:
| Quote: | However it would break many, if not all existing implementations.
Does that matter? Well note how many people post problems with code they
have compiled with VC++ 6.0.
|
Obviously one cannot expect a compiler to conform to rules that haven't
been written yet. But these same old compilers don't implement for-loop
variable scope properly, and they don't implement two-phase lookup, and
probably don't do a host of other things. If people build new programs
on old compilers, then they have to live with what the old compiler can
do. Now, the old implementations would be broken only with respect to
code that actually contains ambiguities in the order of evaluation. If
this is old code, then the behavior is unspecified and generally not
documented, and so is subject to change even in point releases anyway.
If it's new code deliberately written to take advantage of the new
specifications, then it's going to require the new compiler. I just don't
see that it's all that much of an issue.
| Quote: | There is another issue, that of ABIs, unless all current ABIs specify
the same order for passing arguments, changing the current specification
would adversely affect some of them.
|
We're not changing the ABI or the order of passing arguments. We're
changing the order of evaluating arguments, which is altogether different.
Nothing about specifying order of evaluation involves the ABI. It's a
pure language issue.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Wed Jul 06, 2005 9:34 am Post subject: Re: Undefined order of execution of function parameters |
|
|
"M Jared Finder" <jared (AT) hpalace (DOT) com> skrev i meddelandet
news:j5Kdnbsyj_-oVlTfRVn-2w (AT) speakeasy (DOT) net...
| Quote: | Bo Persson wrote:
What is the most effective order to evaluate
f(a + b + c + d + e + f + g + h, x, i + h + g + f + e + c + b + a)?
is it the same on all processors? Should we require one anyway?
If that + acts like the built in +, than it is irrelevant. All three
expressions have no side effects, so there is no noticeable order.
However, the compiler has no way to tell that this is the case for
user
defined operator+ unless it is inlined.
|
My point was rather that, if passing parameters in registers, saving x
until last might leave enough registers available for evaluating the
more complex parameters. Replace the +'s with some random operators, and
add lots of parenthesis. Now what?
| Quote: | My gut feeling is that most function parameter expressions have no
side
effects -- they call only stateless functions. Defining an order of
evaluation here would only affect calls where a programmer assumed
that
there was some order, most likely left to right. I think it would be
much better to make the order of evaluation well defined,
automagically
fixing all these bugs instead of leaving it undefined. The potential
for optimization can be left in by providing a way to tell the
compiler
which functions are stateless and which are statefull.
|
I don't think it is worth the trouble. Possibly because I don't write
code where the order matters.
Should f(++i, ++i) also be well defined?
Bo Persson
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Wed Jul 06, 2005 9:37 am Post subject: Re: Undefined order of execution of function parameters |
|
|
"Hyman Rosen" <hyrosen (AT) mail (DOT) com> skrev i meddelandet
news:200507051510.j65FAouC080164 (AT) horus (DOT) isnic.is...
| Quote: | Francis Glassborow wrote:
There is another issue, that of ABIs, unless all current ABIs specify
the same order for passing arguments, changing the current
specification
would adversely affect some of them.
We're not changing the ABI or the order of passing arguments. We're
changing the order of evaluating arguments, which is altogether
different.
Nothing about specifying order of evaluation involves the ABI. It's a
pure language issue.
|
But specifying a particular order of evaluation might make the ABI's
order of passing arguments less effective. Evaluating in the reverse
order of passing the parameters might not be the best, for example.
Or, if you are passing arguments in registers, there might not be enough
registers left for evaluating the last parameter if that is complicated,
and most registers are already used by the other parameters.
Having one rule for all implementations, just to know the order of
parameter evaluation, seems to violate the "you don't pay for what you
don't use"-principle. In my opinion, the preceived small benefit isn't
worth the risk, and the cost, of changing all current implementations.
Bo Persson
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alan McKenney Guest
|
Posted: Wed Jul 06, 2005 10:02 am Post subject: Re: Undefined order of execution of function parameters |
|
|
Hyman Rosen wrote:
| Quote: | Bo Persson wrote:
By NOT restricting the order of the evaluation, the designers of the C
language left it up to the implementors to do the best they could.
And as has been much discussed here, I maintain that this is now a mistake.
It is unacceptable in C++ to have these order dependencies instead of a
well-defined order of evaluation . Arguments should be evaluated strictly
left-to-right, with each parameter of the called function initialized before
evaluation of the next expression begins. The simple fact that you cannot
call 'f(auto_ptr, auto_ptr)' as 'f(new, new)' without risk of memory leaks
is enough to prove that.
There is simply no justification for such gratuitous implementation-defined
behavior.
|
1. I don't think it's gratuitous. But specifying the order of
evaluation *would* be gratuitous.
Expressions *look* like mathematics, and in mathematics the
order in which arguments are evaluated is irrelevant.
It matters not one whit whether in f( x+x0, y+y0 )
you do the first addition first or the second, any more
than it matters whether in a = (b + c )*(d + e) you
evaluate b+c first or d+e.
To write expressions in which such ordering matters is to
make your code obscure and harder to maintain, regardless of
whether your language defines the order or not.
It's like the classic undefined expression ++i -= ++i +
a[i++];
yes, the Standard could define what it means, but would
we end up with better code by allowing it? I don't think so.
(There's enough inscrutable C/C++ code out there as it is.)
If anything, C (and C++) have too many gratuitous rules.
For example, short-circuiting logical expressions.
I'm sure it seemed like a cute idea at the time, even though
no other language I have used does it.
But see what Scott Meyers says about the advisability of
overloading && and || (and ",") for user-defined types.
2. The fact that no one has posted an example of how specifying
the order of evaluation would seriously hurt compiler
efficiency
doesn't mean that it doesn't, or wouldn't in the future.
I spent many years in the high-performance computing business,
mostly using Fortran, and was confronted every day with the
ways in which language decisions and practices that seemed
harmless or convenient in the days of single-processor, pdp-11
style systems made working on vector and distributed-memory
systems much harder. Anyone here tried to "vectorize" code?
Or use an automatic parallelizer? And C is light-years worse
in this respect than even Fortran-66.
The general experience of people in high-performance computing
is that the more you can express your problem in terms of
what you want done and the less in terms of how you think
it should be done, the easier it is to have software find
an efficient way to do it. Lower-level languages -- which
C (and thus C++) is, at heart -- will always be worse off
than higher-level languages in this respect.
Adding arbitrary rules which add nothing to the expressiveness
of the language, which your proposal is, just make C/C++ more
low-level.
-- Alan McKenney
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|