Reputation: 41
I've been staring at this for about an hour and I honestly have no idea what I'm missing.
#include <iostream>
using namespace std;
void callChain();
double chain(int, int &, int &);
int main()
{
callChain();
}
void callChain() {
int totalInches = 53;
int feet;
int inches;
cout << "\nTesting chain for 53 inches: \nExpected result: 15.46 feet: 4 inches: 5" << endl;
cout << "Actual result: " << chain(totalInches, feet, inches) << " feet: " << feet << " inches: " << inches << endl;
}
double chain(int totalInches, int &feet, int &inches) {
feet = totalInches / 12;
inches = totalInches % 12;
return (feet) * 3.49 + (inches) * .30;
}
The return is correct, so obviously the function is working, but for the life of me I can't figure out why feet and inches aren't changing. Everything is spelled right, I have all my ampersands, but for some reason, the display is showing feet as 8 and inches as 7. I have no idea where those numbers are even coming from.
Upvotes: 2
Views: 95
Reputation: 25518
Just for better illustration of the answers given so far (giving some more details):
std::cout << x
is syntactic sugar for operator<<(std::cout, x)
; as operator<<
returns its first argument, std::cout << x << y;
gets:
operator<<(operator<<(std::cout, x), y);
Obviously, the first argument to the outer call will be evaluated (e. g. the inner call executed) before the the outer call actually is performed – and this is where any guarantees already end, i. e. as order of argument evaluation is unspecified, the compiler is quite well allowed to evaluate y
before the call to the inner operator – including the evaluation of the latter's arguments!
operator<<(operator<<(std::cout, f(x)), x);
Similarly now, the only guarantees here are that f(x)
is called before the inner operator is called and the inner operator being called before the outer one; still, the raw x
can be evaluated at very first...
Obviously, your compiler starts evaluating the arguments from last to first, most likely due to the calling convention in use (quite likely cdecl
; on Windows possibly stdcall
)...
The change in the accepted answer introduces a sequence point between the function calls (old, pre-C++11 wording), which ensures that all effects of the previous call are completed before the call to the next function, i. e. (using new C++11 wording):
operator<<(std::cout, f(x)); // is sequenced b e f o r e next line
operator<<(std::cout, x); // is sequenced a f t e r previous line
Upvotes: 0
Reputation: 234635
Remember that <<
is syntatic sugar for a function call and the order of evaluation of these functions is not necessarily in the order that you think it is. In fact C++ doesn't actually specify the order. So the final parts of you second cout
are printing out the starting values of feet
and inches
.
Call chain(totalInches, feet, inches)
in an intermediate step before the second cout
, perhaps even in this way (Acknowledge @DavidSchwartz):
cout << "Actual result: " << chain(totalInches, feet, inches);
cout << " feet: " << feet << " inches: " << inches << endl;
Upvotes: 5
Reputation: 37217
The evaluation order is unspecified in the ISO C++ standard, according to ostream chaining, output order
To ensure the function is called before those variables are accessed, separate the output chain:
cout << "Actual result: " << chain(totalInches, feet, inches);
cout << " feet: " << feet << " inches: " << inches << endl;
Upvotes: 1