Calling function twice in one printing statement

Apr 18, 2014 at 1:12pm
Why is the output "21", but not "12"?

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

int& add(int &value)
{
    ++value;
    return value;
}

int main()
{
    int result = 0;
    std::cout << add(result) << add(result);
}
Apr 18, 2014 at 2:17pm
Because order of function paramerer evaluaton is unspecified and modifying one value twice between sequence points is undefined behavior.

In your case std::cout << add(result) << add(result); is calculated first.
Then it transformed into std::cout << add(result) << 1;std::cout << 2 << 1;

Your code might output "11" and this will be completely valid because of undefined behavior of your code.
Last edited on Apr 18, 2014 at 2:18pm
Apr 18, 2014 at 3:09pm
So is it true that I should not do this but rather I should use two printing statements?
Apr 18, 2014 at 3:12pm
Either:
1
2
std::cout << add(result);
std::cout << add(result);

or
1
2
int old = add(result);
std::cout << old << add(result);
Apr 18, 2014 at 3:13pm
> I should use two printing statements?

This would suffice:
1
2
const int first = add(result) ;
std::cout << first << add(result);

Apr 18, 2014 at 3:25pm
I think using two printing statements is easier.

I am reading a related question on Stack Overflow about Undefined Behavior and Sequence Points. I post it here in case someone has a similar problem.
http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points
Last edited on Apr 18, 2014 at 3:28pm
Apr 18, 2014 at 3:31pm
Just to note: term Sequence Point is dropped in C++11. It uses sequenced-before now. It is mostly the same. You can read about it here: http://en.cppreference.com/w/cpp/language/eval_order

EDIT: I have read your link. It is discussed there too.
Last edited on Apr 18, 2014 at 3:37pm
Apr 18, 2014 at 3:46pm
Thanks for your reminder. I will also read yours.
Apr 18, 2014 at 4:46pm
To be fair, two function calls to add() are, using C++11 wording, "indeterminately sequenced" (C++98 similar), so the output can only be 12 or 21. The behavior is not undefined, merely unspecified which of the two possibilities take place.
Last edited on Apr 18, 2014 at 4:48pm
Apr 18, 2014 at 6:06pm
Oh, yes: the program must behave as if the CPU instructions that constitute different function calls were not interleaved, even if the functions were inlined

However I do not see anything preventing "22" to be outputted:
calculate right hand side function and store variable in temporary variable of return type of the function (store reference to result)
do the same for left function.
Pass arguments (copy valye references are pointing at).
Apr 18, 2014 at 7:18pm
@MiiNiPaa you are right, I overlooked the fact that the function here returns a reference.

You can certainly have the case where both functions are complete (result == 2) before any of operator<<'s int parameters are initialized from their arguments, so 22 is another allowed result.
Last edited on Apr 18, 2014 at 7:32pm
Topic archived. No new replies allowed.