I came across this rather vague behavior when messing around with code , here's the example :
#include <iostream>
using namespace std;
int print(void);
int main(void)
{
cout << "The Lucky " << print() << endl; //This line
return 0;
}
int print(void)
{
cout << "No : ";
return 3;
}
In my code, the statement with comment //This lineis supposed to print out
The Lucky No : 3, but instead it was printed No : The Lucky 3. What causes this behavior? Does this have to do with C++ standard or its behavior vary from one compiler to another?
The order of evaluation of arguments to a function is unspecified. Your line looks like this to the compiler:
operator<<(operator<<(operator<<(cout, "The Lucky "), print()), endl);
The primary call in the statement is the one with endl as an argument. It is unspecified whether the second argument, endl, is evaluated first or the larger sub-expression:
operator<<(operator<<(cout, "The Lucky "), print())
And breaking that one down, it is unspecified whether the function print() is called first, or the sub-expression:
operator<<(cout, "The Lucky ")
So, to answer your question:
What causes this behavior? Does this has to do with C++ standard or its behavior vary from one compiler to another?
It could vary from compiler to compiler.
Let's call the operator << simply operator .
Now we can write
cout << "The Lucky"
as
operator(cout, "The Lucky")
The result of this operation is cout, and it is passed to next <<, so we can write
operator(operator(cout, "The Lucky"), print() )
It is a function invocation with two parameters, and the standard doesn't say anything about the order of their evaluation.
So with some compilers you really may get
The Lucky No : 3
In my compiler No: The Lucky 3 is the output.... it means that its behaviour varies from compiler to compiler.
Related
Note that I am using a Turbo C++ compiler because we are supposed to learn only Turbo C++ for our school syllabus. Which is why, the cout statement is evaluated from right to left in this case.
Program
#include <iostream.h>
#include <string.h>
void func(char *s, char t[]) {
strcpy(t, "Have fun");
s = "Be\0Cool";
cout << s[0] << ++s << s++ << --s << strupr(s+2) << ++s << s++ << s;
}
int main() {
char x[] = "Hello World!!!", y[] = "Hello World";
func(x, y);
cout << x << y;
return 0;
}
Output
CCOOLeeOOLBeBeHello World!!!Have fun
I feel the output should be:
CCooleeOOLBeBeHello World!!!Have fun
Because in the ++s part of the cout statement (second position), the pointer is at index 3 of the string s, so only 'Cool' should be printed. Instead 'COOL' is being printed. Why does this happen?
Tests with Visual Studio 2019
For comparison purpose, in Visual Studio 2019 (DEBUG), if we make required change to compile the code, then the program crash because we try to modify a constant string ("Be\0Cool").
If we do additional change to avoid the crash (by using a local array), the output is:
CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
If we split cout << s[]…; line to multiple calls to cout (one before each <<), then the output would be:
BeeeCOOLCOOLHello World!!!Have fun
Or if we add a line after each output, we get:
B
e
e
e
COOL
COOL
Hello World!!!
Have fun
Trying to understand the output of Turbo C++
If we then reverse each call to cout to start with the last (i.e. cout << s<< endl;) and end with first (cout << s[0] << endl), then we get:
Be
Be
OOL
e
e
COOL
C
Hello World!!!
Have fun
If we manually write that starting with the third last line and up and then the two last line in order without space, we get:
CCOOLeeOOLBeBeHello World!!!Have fun
Which is exactly what you got as an output.
Thus, it appears that Turbo C++ evaluate every expression from the right to the left.
Notes about required changes to compile (and run)
<iostream.h> is not available so I have to use <iostream> instead.
#define _CRT_SECURE_NO_WARNINGS must be added at top because some functions are not secure (and won't compile by default).
using namespace std; to avoid making more change to the code.
Add cast in s = (char *)"Be\0Cool"; so that line compile.
This lead to a crash because data is constant and we try to modify it.
Remove the cast and instead write char data[] = "Be\0Cool"; s = data;
The program run but the output is CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
In fact, this is undefined behavior. It just happen to be the actual output.
Undefined behavior
Some things are not defined by the standard and thus are not required to work a certain way. Well, as expected if read-only memory is not supported, it works like read-write memory.
For the order of evaluation, common possibilities are:
left to right
right to left
whatever is more optimal
Also since a variable is modified more than once, the value of s is not defined during the evaluation and afterward. The easy to remember rule is to avoid modifying the same variable more than once in a single expression.
About strupr
That function modify the string up to the terminating null character. In your case, it would convert to uppercase every letters from whatever value s has at the moment of the call.
When I use cout to print the value of my variable, it doesn't give me the same answer if I use two statements in one line or two lines. Can you help me?
int a= 5;
cout << a << endl;
cout << a-- << endl;
cout << a << a-- << endl;
// it gives me different answer, why?
//they are basically same thing
cout << a << a-- << endl;
is translated as:
cout.operator<<(a).operator<<(a--).operator<<(endl);
In such a case, the language does not guarantee which of the arguments will be evaluated first. A compiler is free to choose whichever evaluation order makes sense to them. Please note that the function call order is guaranteed but not the evaluation order of the function arguments.
If you are able to use c++17, the standard has changed for the << operator. It guarantees an evaluation order that makes sense and you will get the expected result.
There are no guarantees of evaluation order prior to C++17 with operator <<, but since" C++17, left to right order is guarantee for operator <<.
See eval_order for more details.
I feel I'm asking a very basic question, but I haven't been able to find an answer here or in Google. I recall we were taught this at school, but alas it has vanished over years.
Why does cout.precision() (std::ios_base::precision()) affect the whole stream when called in the middle of the output list? I know the rule that std::setprecision() should be used to change precision on the fly, and that cout.precision() is going to spoil the output with the value it returns. But what is the mechanics of this? Is it due to buffering? The manuals state these "do the same thing", but empirically I can see it's not entirely true.
MCVE:
const double test = 1.2345;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << test << endl << cout.precision(3) << test << endl;
// Output:
// 1.234
// 21.234
// after the same init
cout.precision(2);
cout << test << endl << setprecision(3) << test << endl;
// Output
// 1.23
// 1.234
Is this "implementation specific / not defined by the standard"?
Feel free to mark this as duplicate, for I haven't been able to find it on SO.
The order of function argument evaluation is unspecified. When you call std::cout.precision(n) the precision of std::cout' is set at the point this call is evaluated. In your expression
cout << test << endl << cout.precision(3) << test << endl;
the cout.precision(3) is, apparently, called first thing which the compiler is entirely allowed to do. Remember that the compiler considers the above statement equivalent to
std::cout.operator<<(test)
.operator<<(std::endl)
.operator<<(std::cout.preision(3))
.operator<<(test)
.operator<< (std::endl);
Practically, it seems for your compiler function arguments are evaluated right to left. Only then the different shift operators are executed. As a result, the precision gets changed before the output is done.
The use of manipulators like std::setprecision(n) avoids relying on the order subexpressions are evaluated: the temporary created from std::setprecision(n) is created whenever it is. The effect is then applied when the appropriate shift operator is called. Since the shift operators have to be called in the appropriate order, the use of the manipulator happens at a known place.
The exact time when cout.precision(3) is evaluated in your first example is not defined, because its value serves as an argument for a function call. OTOH with the second example, the time when setprecision(3) is inserted to the stream is very well defined - i.e. after endl is inserted and before test (2nd time). Therefor the first version will not produce reliable results (what you get may be different on different implementations), but the second version will.
See this question for a more detailed explanation. (The question there doesn't use operators, but the principle is the same - calling a member function on the return value of another function.)
This question already has answers here:
cout << order of call to functions it prints?
(3 answers)
Closed 9 years ago.
I have following simple program that initialize values for three variables and then gives output as expression.
#include<iostream>
#include<conio.h>
using namespace std;
int main()
{
volatile int a = 10, b = 20, c = 30;
cout << a+b+c << " " << (c=c*2) << " "<< (b =b*2);
getch();
return 0;
}
Output I am getting for above code is
110 60 40
But a=10,b=20 and c=30 so a+b+c should be 10+20+30 = 60
This is because the arguments to the function are processed from right to left but are printed from left to right.
In C++, the order of evaluation of function arguments is undefined. That is, in the statement
std::cout << a+b+c << " " << (c=c*2) << " "<< (b =b*2);
you get different results depending on which subexpressions are evaluated first. A compiler can choose to evaluate the arguments to the output operators from left to right but it is also free to evaluate them in a different order, e.g., right to left, then do the appropriate functions calls.
The output from this code is undefined.
In C++, if assigning a variable, you are only allowed to use in the same statement for purposes of calculating the new value. Any other use has undefined effect.
(Note, you evaluate c for the purposes of printing (the 1st print clause), and for the purposes of calculating a new c (the c=c*2).
The later use is sanctioned, the former isn't.
Most compilers will calculate the first use of c as either the value before OR the value after the assignment, but in fact they arent even obliged to have it evaluate to anything related. And even if related, may not be a value it ever logically held, eg if the assignment were (c=2*c+5), you could just as easily find this mapped to c*=2, c+=5, and the first print clause might get the intermediate state, rather than the starting or end state.
The same problem exists for b. Compilers cant even be assume to be consistent in their handling of this, since what they do may reasonably depend on register allocation, which depends on local code.
I have a custom stack class. Most of the code can be seen here:
Member functions of a templated class, that take a template type as argument
I fill the stack like so:
stack <int> Astack;
Astack.Push(1); Astack.Push(2); Astack.Push(3); Astack.Push(4);
Then I do this:
cout << Astack.Pop() << Astack.Pop() << Astack.Pop() << Astack.Pop() <<endl;
and get this: 1234
However, if I do this:
cout << Astack.Pop(); cout << Astack.Pop(); cout << Astack.Pop(); cout << Astack.Pop();
I get this: 4321, which is obviously what I want.
So, what gives?
The order of evaluation of the function calls is unspecified. Your first expression basically boils down to this:
cout << a << b << c << d;
Each of a, b, c, and d are calls to Astack.Pop(). The compiler can generate code that evaluates those calls in any order it chooses.
You should avoid writing expressions that rely on a particular order of evaluation of parts of the expression. In general, it's not safe (and even when it is safe, it is usually quite confusing).
In the first version the arguments to cout are evaluated from right to left. You never actually specify which order they should be evaluated in, so the one on the right is evaluated first, popping the 4, and so on.
There is something known as Unspecified Behaviour defined by the ISO C++ Standard. Your code-snippet is just an example of that.