-2

I have this problem with my functions.

in the main function I have this result(param, param) function which takes 2 functions as parameters.

result(name(), score());

However when the code executes the score() function executes first and not the name() function. why does that happen.

(Also another problem that arises from the score() function executing first and not the name() function is that I get the \n read and the name() function is skipped altogether. However I know how to fix that I just need to know why isn't the name() function executed first. ).

I found this here: http://en.cppreference.com/w/cpp/language/eval_order.

Order of evaluation of the operands of any C++ operator, including the order of evaluation of function arguments in a function-call expression, and the order of evaluation of the subexpressions within any expression is unspecified (except where noted below). The compiler will evaluate them in any order, and may choose another order when the same expression is evaluated again.

There is no concept of left-to-right or right-to-left evaluation in C++, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() or f2() at run time.**

But my program always executes the score() function first. And above it states that it is random so I should at least have the name() function executed first sometimes right?

Full code is here for reference.

#include <iostream>
#include <string>

using namespace std;

string name()
{
    string fname;
    cout << "Please type your full name: ";
    getline(cin, fname);
    return fname;
}

int score()
{
    int points;
    cout << "Please type your score: ";
    cin >> points;
    return points;
}

void result(string fname, int points)
{
    cout << "Ok " << fname << ", your score of " << points << " is ";
    if (points > 100)
    {
        cout << "Impossible";
    }
    else if (points == 100)
    {
        cout << "Perfect!!!";
    }
    else if (points >= 85 && points < 100)
    {
        cout << "Amazing!!";
    }
    else if (points >= 70 && points < 85)
    {
        cout << "Good!";
    }
    else if (points >= 50 && points < 70)
    {
        cout << "Ok.";
    }
    else if (points < 50)
    {
        cout << "Bad...";
    }
    else
    {
        cout << "Incorrect input";
    }
}
int main()
{
    result(name(), score());
    return 0;
}
Community
  • 1
  • 1
Johnson
  • 145
  • 4
  • 10
  • 1
    On coliru, clang++ [calls name() first](http://coliru.stacked-crooked.com/a/8491dfe97dc3a688) and g++ [calls score() first](http://coliru.stacked-crooked.com/a/e63c6a5157fedb98) – Cubbi Jan 07 '15 at 02:39

2 Answers2

9

In this line:

result(name(), score());

the order of evaluation for the function arguments is not defined. It just so happens that this is the order of evaluation with your particular compiler (and compiler flags). If you want the functions to be executed in a particular order then you'll ned to call them in the required order first:

string s = name();
int t = score();
result(s, t);
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • Yea i know that's why i posted the reference above. But why is the second function ALWAYS executed first then? – Johnson Jan 06 '15 at 21:58
  • 3
    It just so happens that this is the order of evaluation with your particular compiler (and compiler flags) - it could well be different with a different compiler (or even with just different optimisation settings). – Paul R Jan 06 '15 at 21:59
  • The order of function execution may be based on what easiest for the compiler to evaluate or to emit code for. Sometimes, evaluating parameters from right to left is simpler for the compiler. – Thomas Matthews Jan 06 '15 at 22:00
  • Yea but i am testing to see how to use functions as parameters so the above answer wont do that for me. – Johnson Jan 06 '15 at 22:04
  • 3
    You have to accept that if you pass functions as parameters then the order of evaluation is unspecified, i.e. you can't rely on it. For most function calls (i.e. in well written code with no side effects) this does not matter, but in your example it obviously does matter. – Paul R Jan 06 '15 at 22:06
  • Oh thanks so for example if i am lets say forced to use functions as parameters then i should take all precautions like in the above code that the \n is read i should do something to fix it in case score() gets executed first? – Johnson Jan 06 '15 at 22:09
  • 1
    You're never *forced* to use functions as parameters (unless it's some kind of bizarre homework exercise) - when order of execution matters then it's up you to ensure that the necessary constraints are met. – Paul R Jan 06 '15 at 22:13
  • Tea i know but is there any possibility where it can be better to use functions as parameters instead of how they are used in this example by you Paul R meaning setting their value to 2 variables. Also chose it as best answer thanks :P – Johnson Jan 06 '15 at 22:24
  • As I said above, functions with no side-effects are fine, in general. So calling something like `pow()` or `cos()` as a function argument is fine. Your functions have side-effects though, as they perform I/O, so synchronization is required. You could probably fix this by re-factoring your methods so that I/O is handled separately. – Paul R Jan 06 '15 at 22:34
5

It's not random, it's unspecified.

Which means that the compiler is free to do what it wants. Here the compiler decided that it's best to always call score() before name(), and will not change its mind without a good reason. Maybe another compiler would have decided something else, maybe it depends on the phase of the moon, you can't tell and you're not supposed to try to guess what's going to happen.

Unspecified means that you can't expect it to behave in any particular way, you can't rely on it.

tux3
  • 7,171
  • 6
  • 39
  • 51