This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
cout << order of call to functions it prints?
What is the difference between order and associativity when evaluating a compound expression?
In the following example, I don't see the effect of order on the result of expression. The result is always 3 like the functions would have been called from left to right as arithmetic operators being left associative.
#include <iostream>
using std::cout;
using std::endl;
int Func1(int &i)
{
return i;
}
int Func2(int &i)
{
return i++;
}
int main()
{
for (int index = 0; index < 999999999; index++)
{
int i = 0;
int result = (Func2(i) + Func1(i) + Func1(i) + Func2(i));
cout << result << endl;
}
}
int result = (Func2(i) + Func1(i) + Func1(i) + Func2(i));
The order in which these functions are called is unspecified by the language!
The section $5/4 from the C++ Standard (2003) reads,
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified.
So the free advice is : avoid writing such code. They're non-portable!
The result is very likely to be the same if you run the code multiple times, using the same compiler with the same compile options. However, if you change the options or try another compiler, you can get a different result.
As you use only simple functions on ints, there is nothing much to be gained from calling the functions in a different order, so either left-to-right or right-to-left would be the obvious choice. And your test code can't tell the difference! :-)
Related
for the expression
(func1() * func2()) + func3()
will func1() * func2() be evaluated first as it has brackets or can the functions be called in any order like
first func3() and then (func1() * func2())
The functions can be called in any order.
Precedence of operators has got nothing to do anything with the order of evaluation of operands.
The C or C++ Standard doesn't determine the order in which the functions would be called. .
The order of evaluation of subexpressions, including
the arguments of a function call and
operands of operators (e.g., +, -, =, * , /), with the exception of:
the binary logical operators (&& and ||),
the ternary conditional operator (?:), and
the comma operator (,)
is Unspecified
For example
int Hello()
{
return printf("Hello"); /* printf() returns the number of
characters successfully printed by it
*/
}
int World()
{
return printf("World !");
}
int main()
{
int a = Hello() + World(); //might print Hello World! or World! Hello
/** ^
|
Functions can be called in either order
**/
return 0;
}
You can't make any assumptions about the order in which these functions will be called. It's perfectly valid for the compiler to call these functions in any order, assign the results to temporaries, and then use these temporary values to calculate the result of the expression.
These calls can be made in any order. You want to learn about C++ sequence points C++ sequence points.
Parenthesis in C/C++ force order of operations. func1() * func2() will be added to func3(), but the compiler can choose to call the functions in whatever order it wishes before passing in the results to the multiplication / addition operation.
It's natural to think that A+B is evaluated before C in this psudocode:
(A+b)*C
But in fact this is not so. The Standard says that the order of evaluation for all expressions is "Unspecified", unless otherwise specified by the Standard:
5/4 [expr]:
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified
The Standard then goes on to identify a parenthesized expression as a "Primary expression" but does not specify the order of evaluation for Primary expressions. (5.1/5).
In Standardese, "Unspecified" does not mean "Undefined." Rather it means "Implementation Defined, but no documentation is required." So you might not even be able to say what the order of evaluation is for a specific compiler.
Here is a simple program illustrating the behavior:
#include <iostream>
#include <string>
using namespace std;
class Foo
{
public:
Foo(const string& name) : name_(name) {++i_; cout << "'" << name << "'(" << i_ << ")\n"; };
operator unsigned() const { return i_; }
Foo operator+(const Foo& rhs) const { string new_name = name_; new_name += "+"; new_name += rhs.name_; return Foo(new_name); }
private:
string name_;
static unsigned i_;
};
unsigned Foo::i_ = 0;
int main()
{
(Foo("A") + Foo("B")) + Foo("C");
}
On my MSVC10 running in Debug/x64 on Win7, the output happened to be:
'C'(1)
'B'(2)
'A'(3)
'A+B'(4)
'A+B+C'(5)
Consider the following program.
#include<iostream>
using namespace std;
void fn(int a, int b)
{
cout << a;
cout << b;
}
int main()
{
int a = 10;
fn(a++, --a);
fn(a--, ++a);
return 0;
}
I don't understand the output I get (gcc 11.2):
9101110
Shouldn't a++ be evaluated first? How can fn then get a 9? Is this undefined behavior or simply "indeterminate"? Did C++17 change in this respect?
This is undefined behavior. The order of parameter evaluation is unspecified.
See here.
So this question is irrelevant and code like this should never be used.
The output can be 9 10 11 10 on one compiler, and a totally different value on another compiler (while both compilers remain standard-complaint).
This question already has answers here:
Order of evaluation in C++ function parameters
(6 answers)
Warn about UB in argument evaluation order
(1 answer)
Closed 2 years ago.
I'm new at programming. This is part of my code:
double logic(double a,double b)
{
(Code Here...)
}
double inputDouble(double x)
{
std::cout << "Please, input a floating number: ";
std::cin >> x;
std::cout << std::endl;
return x;
}
int main()
{
double a,b;
std::cout << logic(inputDouble(a),inputDouble(b));
return 0;
}
I've noticed the problem on the compiler, them I've checked the debug windows and the problem that I'm having is that when I insert a value on 'a' by 'inputDouble' function, it goes to 'b', and vice-versa. So at the end of the program what I get in 'logic' function is: double a=b(From main()), double b=a(From main()). I hope and am grateful to someone who can explain to me what I'm doing wrong so the variables are being assigned on the wrong places. And I also apologize if there is any gramatical mistake on this post as english is not my first language.
The expression:
logic(inputDouble(a),inputDouble(b))
does not guarantee the order in which those calls to inputDouble() are made, just that they're both complete before the call to logic(). So it may call the a one first, or it may call the b one first(a).
To guarantee order, you can use something like:
double inputDouble() { // slight change, see below.
double x;
std::cout << "Please, input a floating number: ";
std::cin >> x;
std::cout << std::endl;
return x;
}
int main() {
double a = inputDouble(); // guarantee get 'a' first.
double b = inputDouble();
std::cout << logic(a, b);
return 0;
}
You could also use:
double a = inputDouble(); // guarantee get 'a' first.
std::cout << logic(a, inputDouble());
but I prefer the first one for consistency.
You'll notice a slight change to the inputDouble() function as well to remove the parameter, no useful purpose is served by passing the uninitialised values to the function, then over-writing and returning it.
Instead, I've just used a local variable to receive the value and return it.
A more robust program would also ensure that user input was valid but that can be left for a different question, since it almost certainly already exists on this site.
(a) For the language lawyers amongst us, this is covered in C++20 [expr.call] /8 (my emphasis):
The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter. [Note: All side effects of argument evaluations are sequenced before the function is entered].
for the expression
(func1() * func2()) + func3()
will func1() * func2() be evaluated first as it has brackets or can the functions be called in any order like
first func3() and then (func1() * func2())
The functions can be called in any order.
Precedence of operators has got nothing to do anything with the order of evaluation of operands.
The C or C++ Standard doesn't determine the order in which the functions would be called. .
The order of evaluation of subexpressions, including
the arguments of a function call and
operands of operators (e.g., +, -, =, * , /), with the exception of:
the binary logical operators (&& and ||),
the ternary conditional operator (?:), and
the comma operator (,)
is Unspecified
For example
int Hello()
{
return printf("Hello"); /* printf() returns the number of
characters successfully printed by it
*/
}
int World()
{
return printf("World !");
}
int main()
{
int a = Hello() + World(); //might print Hello World! or World! Hello
/** ^
|
Functions can be called in either order
**/
return 0;
}
You can't make any assumptions about the order in which these functions will be called. It's perfectly valid for the compiler to call these functions in any order, assign the results to temporaries, and then use these temporary values to calculate the result of the expression.
These calls can be made in any order. You want to learn about C++ sequence points C++ sequence points.
Parenthesis in C/C++ force order of operations. func1() * func2() will be added to func3(), but the compiler can choose to call the functions in whatever order it wishes before passing in the results to the multiplication / addition operation.
It's natural to think that A+B is evaluated before C in this psudocode:
(A+b)*C
But in fact this is not so. The Standard says that the order of evaluation for all expressions is "Unspecified", unless otherwise specified by the Standard:
5/4 [expr]:
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified
The Standard then goes on to identify a parenthesized expression as a "Primary expression" but does not specify the order of evaluation for Primary expressions. (5.1/5).
In Standardese, "Unspecified" does not mean "Undefined." Rather it means "Implementation Defined, but no documentation is required." So you might not even be able to say what the order of evaluation is for a specific compiler.
Here is a simple program illustrating the behavior:
#include <iostream>
#include <string>
using namespace std;
class Foo
{
public:
Foo(const string& name) : name_(name) {++i_; cout << "'" << name << "'(" << i_ << ")\n"; };
operator unsigned() const { return i_; }
Foo operator+(const Foo& rhs) const { string new_name = name_; new_name += "+"; new_name += rhs.name_; return Foo(new_name); }
private:
string name_;
static unsigned i_;
};
unsigned Foo::i_ = 0;
int main()
{
(Foo("A") + Foo("B")) + Foo("C");
}
On my MSVC10 running in Debug/x64 on Win7, the output happened to be:
'C'(1)
'B'(2)
'A'(3)
'A+B'(4)
'A+B+C'(5)
I'm a TA for an intro C++ class. The following question was asked on a test last week:
What is the output from the following program:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x) << endl << myFunc(x) << endl;
}
The answer, to me and all my colleagues, is obviously:
8
27
64
But now several students have pointed out that when they run this in certain environments they actually get the opposite:
64
27
8
When I run it in my linux environment using gcc I get what I would expect. Using MinGW on my Windows machine I get what they're talking about.
It seems to be evaluating the last call to myFunc first, then the second call and then the first, then once it has all the results it outputs them in the normal order, starting with the first. But because the calls were made out of order the numbers are opposite.
It seems to me to be a compiler optimization, choosing to evaluate the function calls in the opposite order, but I don't really know why. My question is: are my assumptions correct? Is that what's going on in the background? Or is there something totally different? Also, I don't really understand why there would be a benefit to evaluating the functions backwards and then evaluating output forward. Output would have to be forward because of the way ostream works, but it seems like evaluation of the functions should be forward as well.
Thanks for your help!
The C++ standard does not define what order the subexpressions of a full expression are evaluated, except for certain operators which introduce an order (the comma operator, ternary operator, short-circuiting logical operators), and the fact that the expressions which make up the arguments/operands of a function/operator are all evaluated before the function/operator itself.
GCC is not obliged to explain to you (or me) why it wants to order them as it does. It might be a performance optimisation, it might be because the compiler code came out a few lines shorter and simpler that way, it might be because one of the mingw coders personally hates you, and wants to ensure that if you make assumptions that aren't guaranteed by the standard, your code goes wrong. Welcome to the world of open standards :-)
Edit to add: litb makes a point below about (un)defined behavior. The standard says that if you modify a variable multiple times in an expression, and if there exists a valid order of evaluation for that expression, such that the variable is modified multiple times without a sequence point in between, then the expression has undefined behavior. That doesn't apply here, because the variable is modified in the call to the function, and there's a sequence point at the start of any function call (even if the compiler inlines it). However, if you'd manually inlined the code:
std::cout << pow(x++,3) << endl << pow(x++,3) << endl << pow(x++,3) << endl;
Then that would be undefined behavior. In this code, it is valid for the compiler to evaluate all three "x++" subexpressions, then the three calls to pow, then start on the various calls to operator<<. Because this order is valid and has no sequence points separating the modification of x, the results are completely undefined. In your code snippet, only the order of execution is unspecified.
Exactly why does this have unspecified behaviour.
When I first looked at this example I felt that the behaviour was well defined because this expression is actually short hand for a set of function calls.
Consider this more basic example:
cout << f1() << f2();
This is expanded to a sequence of function calls, where the kind of calls depend on the operators being members or non-members:
// Option 1: Both are members
cout.operator<<(f1 ()).operator<< (f2 ());
// Option 2: Both are non members
operator<< ( operator<<(cout, f1 ()), f2 () );
// Option 3: First is a member, second non-member
operator<< ( cout.operator<<(f1 ()), f2 () );
// Option 4: First is a non-member, second is a member
cout.operator<<(f1 ()).operator<< (f2 ());
At the lowest level these will generate almost identical code so I will refer only to the first option from now.
There is a guarantee in the standard that the compiler must evaluate the arguments to each function call before the body of the function is entered. In this case, cout.operator<<(f1()) must be evaluated before operator<<(f2()) is, since the result of cout.operator<<(f1()) is required to call the other operator.
The unspecified behaviour kicks in because although the calls to the operators must be ordered there is no such requirement on their arguments. Therefore, the resulting order can be one of:
f2()
f1()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or:
f1()
f2()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or finally:
f1()
cout.operator<<(f1())
f2()
cout.operator<<(f1()).operator<<(f2());
The order in which function call parameters is evaluated is unspecified. In short, you shouldn't use arguments that have side-effects that affect the meaning and result of the statement.
Yeah, the order of evaluation of functional arguments is "Unspecified" according to the Standards.
Hence the outputs differ on different platforms
As has already been stated, you've wandered into the haunted forest of undefined behavior. To get what is expected every time you can either remove the side effects:
int myFunc(int &x) {
int temp = x * x * x;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x+1) << endl << myFunc(x+2) << endl;
//Note that you can't use the increment operator (++) here. It has
//side-effects so it will have the same problem
}
or break the function calls up into separate statements:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
}
The second version is probably better for a test, since it forces them to consider the side effects.
And this is why, every time you write a function with a side-effect, God kills a kitten!