This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
For the code below:
main() {
int i = 1 ;
cout << i << ++i << i++ ;
}
Why do I get the output as 331 instead of what was expected i.e 122 ?
( Same is the case even if I use printf instead of cout ?)
<< is a function, namely something like ostream& operator<<(ostream& lhs, RhsType rhs).
cout << a;
is equivalent to
operator<<(cout, a);
The function returns lhs, that is return lhs, - so in the above examples cout is returned.
So your example
cout << i << ++i << i++ ;
is equivalent to
operator<<(operator<<(operator<<(cout, i), ++i), i++);
Correction C++ does not specify which order the increment operations are performed. It seems logical to you and me that the most nested would go first, but as far as the compiler is concerned it is free to execute the increment whenever it likes. It is the same behaviour as a function like myFunc(cout, i++, ++i, i) where the order in which the increments are evaluated is undefined. The only thing guaranteed is the functions are evaluated inside to outside.
The compiler is free to change the order of evaluation. You are changing i multiple times on the same statament which causes undefined behaviour.
This is the reason why you should not write such code.
I'm sure this will give you different results with different compilers.
Using Visual C++ this gives you different output when run in Debug and Release versions.
The output you observed can be explained in this way: The expression is evaluated right-to-left *before* being passed to cout or printf for output.
Starting value is 1
i++ is post increment, ie it will print the value (1) and then
increment to 2: output 1
++i is pre-incremen, so 2 becomes 3 before it is printed: output 3
finally, the current value of i (3) is printed: output 3
These respective values are passed to the output routine.
To clarify, my answer only tries to explain the observed behavior, not lay down hard and fast rules for how the compiler or output routines order their evaluations/actions.
Having said that, this type of code is not good practice and quite likely to cause all sorts of problems that could be avoided.
Related
This question already has answers here:
Returning a reference to a local variable in C++
(3 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
int& foo()
{
int i = 4;
return i;
}
int main()
{
int& j = foo();
cout << j << endl;
cout << j << endl;
cout << j << endl;
cout << j << endl;
cout << j << endl;
cout << j << endl;
return 0;
}
In here, I would expect the first cout of j to output garbage because of the fact that the local variable i, which j is referencing, has gone out of scope. However, it seems consistently the first cout statement outputs the correct value that would be outputted if i was still in scope which is 4. After that, every cout statement prints garbage that is the same value. Here is an example of some output I've been getting:
4
528494
528494
528494
528494
528494
Press any key to continue . . .
Why is j not immediately printing out garbage the first cout statement. Shouldn't i have already gone out of scope?
The rule is not "using a variable after it has passed out of scope gives garbage output". It is that using a reference to a variable that has gone out of scope is undefined behaviour according to all C++ standards.
Undefined behaviour means the C++ standard provides no guarantee whatsoever about what happens. A consequence is that, when behaviour is undefined, any actual observable result is permitted. Garbage output is only one possible observable result.
That means any explanation of the behaviour you're seeing will be specific to your implementation (compiler, your chosen optimisation or debugging settings, etc, memory management by your host system, ....). The behaviour may also vary over time, since - when behaviour is undefined - there is no requirement that any particular behaviour occurs consistently.
As a generic explanation, in your specific case, it is probably related to how your compiler manages usage of machine registers by your program. The variable i in foo() may be stored in a register, then that register may not be cleared immediately, so the value 4 is retrieved from it in the first cout << j << endl statement. The working of output streams (implementation of operator<<() or endl) may then use the same register internally - since there is absolutely no way that C++ code with well-defined behaviour can access those registers directly - and therefore overwrite it.
But that's just a guess. As I said, it depends on the implementation - that's why I used the word "may" so liberally in the preceding paragraph. When behaviour is undefined (by the standard) then a compiler is permitted to do anything. You could see a completely different behaviour by tweaking optimisations settings or next time you update your compiler. Different compilers may do things completely differently as well.
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
I know that using const_cast is generally bad idea, but I was playing around with it and I came across a weird behaviour, where:
Two pointers have the same address value, yet when de-referenced, give different data values.
Does anyone have an explanation for this?
Code
#include <iostream>
int main()
{
const int M = 10;
int* MPtr = const_cast<int*>(&M);
(*MPtr)++;
std::cout << "MPtr = " << MPtr << " (*MPtr) = " << (*MPtr) << std::endl;
std::cout << " &M = " << &M << " M = " << M << std::endl;
}
Output
MPtr = 0x7fff9b4b6ce0 (*MPtr) = 11
&M = 0x7fff9b4b6ce0 M = 10
The program has undefined bahaviour because you may not change a const object.
From the C++ Standard
4 Certain other operations are described in this International
Standard as undefined (for example, the effect of attempting to modify
a const object). [ Note: This International Standard imposes no
requirements on the behavior of programs that contain undefined
behavior. —end note ]
So, aside from the "it's undefined behaviour" (which it is), the compiler is perfectly fine to use the fact that M is a constant, thus won't change, in the evaluation of cout ... << M << ..., so can use an instruction that has the immediate value 10, instead of the actual value stored in the memory of M. (Of course, the standard will not say how this works, more than "it's undefined", and compilers are able to choose different solutions in different circumstances, etc, etc, so it's entirely possible that you'll get different results if you modify the code, use a different compiler, different version of compiler or the wind is blowing in a different direction).
Part of the tricky bit with "undefined behaviour" is that it includes things that are "perfectly what you may expect" as well as "nearly what you'd expect". The compiler could also decide to start tetris if it discovers this is what you are doing.
And yes, this is very much one of the reasons why you SHOULD NOT use const_cast. At the very least NOT on things that were originally const - it's OK if you have something along these lines:
int x;
void func(const int* p)
{
...
int *q = const_cast<int *>(p);
*q = 7;
}
...
func(&x);
In this case, x is not actually const, it just becomes const when we pass it to func. Of course, the compiler may still assume that x is not changed in func, and thus you could have problems....
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.
The associativity of stream insertion operator is rtl, forgetting this fact sometimes cause to runtime or logical errors.
for example:
1st-
int F()
{
static int internal_counter c=0;
return ++c;
}
in the main function:
//....here is main()
cout<<”1st=”<<F()<<”,2nd=”<<F()<<”,3rd=”<<F();
and the output is:
1st=3,2nd=2,3rd=1
that is different from what we expect at first look.
2nd-
suppose that we have an implementation of stack data structure like this:
//
//... a Stack<DataType> class ……
//
Stack<int> st(10);
for(int i=1;i<11;i++)
st.push(i);
cout<<st.pop()<<endl<<st.pop()<<endl<<st.pop()<<endl<<st.pop()<<endl;
expected output is something like:
10
9
8
7
but we have:
7
8
9
10
There is no internal bug of << implementation but it can be so confusing...
and finally[:-)] my question: is there any way to change associativity of an operator by overloading it?
do you think this could be not reverse? i mean is it possible to change order by modifying or changing an open source STL?
No there isn't. But I think you may be mixing up associativity with evaluation order. The only operators that specify an evalualtion order are &&, || and , (comma). When you say:
cout<<st.pop()<<endl<<st.pop()<<endl<<st.pop()<<endl<<st.pop()<<endl;
the compiler can evaluate sub-expressions such as st.pop() in any order it likes, which is what causes the unexpected output.
The only things that are right-associative are the assignment operators. See §5.4 to 5.18 of the standard. The << operators are evaluated left-to-right or the messages would be backward in grammar, not in content. The content is due to side effects, which are unordered in C++ except (as Neil mentions) for "short-circuit" && and ||, and comma.
To see how this is an order of evaluation issue and not an associativity issue, modify your code to this:
int a = st.pop();
int b = st.pop();
int c = st.pop();
cout << a << endl << b << endl << c << endl;
I know that cout have buffer several days ago, and when I google it, it is said that the buffer is some like a stack and get the output of cout and printf from right to left, then put them out(to the console or file)from top to bottem. Like this,
a = 1; b = 2; c = 3;
cout<<a<<b<<c<<endl;
buffer:|3|2|1|<- (take “<-” as a poniter)
output:|3|2|<- (output 1)
|3|<- (output 2)
|<- (output 3)
Then I write a code below,
#include <iostream>
using namespace std;
int c = 6;
int f()
{
c+=1;
return c;
}
int main()
{
int i = 0;
cout <<"i="<<i<<" i++="<<i++<<" i--="<<i--<<endl;
i = 0;
printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );
cout<<f()<<" "<<f()<<" "<<f()<<endl;
c = 6;
printf("%d %d %d\n" , f() , f() ,f() );
system("pause");
return 0;
}
Under VS2005, the output is
i=0 i++=-1 i--=0
i=0 i++=-1 i--=0
9 8 7
9 8 7
It seems that the stack way is right~
However, I read C++ Primer Plus yesterday, and it is said that the cout work from left to right, every time return an object(cout), so "That’s the feature that lets you concatenate output by using insertion". But the from left to right way can not explain cout<
Then Alnitak tell me that, "The << operator is really ostream& operator<<(ostream& os, int), so another way of writing this is:
operator<< ( operator<< ( operator<< ( cout, a ), b ), c )",
If the rightest argument is first evaluated, it can be some explained.
Now I'm confused about how cout's buffer work, can somebody help me?
You are mixing a lot of things. To date:
Implementation details of cout
Chained calls
Calling conventions
Try to read up on them separately. And don't think about all of them in one go.
printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );
The above line invokes undefined behavior. Read the FAQ 3.2. Note, what you observe is a side-effect of the function's calling convention and the way parameters are passed in the stack by a particular implementation (i.e. yours). This is not guaranteed to be the same if you were working on other machines.
I think you are confusing the order of function calls with buffering. When you have a cout statement followed by multiple insertions << you are actually invoking multiple function calls, one after the other. So, if you were to write:
cout << 42 << 0;
It really means: You call,
cout = operator<<(cout, 42)
and then use the return in another call to the same operator as:
cout = operator<<(cout, 0)
What you have tested by the above will not tell you anything cout's internal representation. I suggest you take a look at the header files to know more.
Just as a general tip, never ever use i++ in the same line as another usage of i or i--.
The issue is that function arguments can be evaluated in any order, so if your function arguments have any side-effects (such as the increment and decrement operations) you can't guarantee that they will operate in the order you expect. This is something to avoid.
The same goes for this case, which is similar to the actual expansion of your cout usage:
function1 ( function2 ( foo ), bar );
The compiler is free to evaulate bar before calling function2, or vice versa. You can guarantee that function2 will return before function1 is called, for example, but not that their arguments are evaluated in a specific order.
This becomes a problem when you do something like:
function1 ( function2 ( i++), i );
You have no way to specify whether the "i" is evaluated before or after the "i++", so you're likely to get results that are different than you expect, or different results with different compilers or even different versions of the same compiler.
Bottom line, avoid statements with side-effects. Only use them if they're the only statement on the line or if you know you're only modifying the same variable once. (A "line" means a single statement plus semicolon.)
What you see is undefined behavior.
Local i and global c are added/subtracted multiple times without sequence point. This means that values you get can be about anything. Depends on compiler, possibly also processor architecture and number of cores.
The cout buffer can be thought as queue, so Alnitak is right.
In addition to the other answers which correctly point out that you are seeing undefined behavior, I figured I'd mention that std::cout uses an object of type std::streambuf to do its internal buffering. Basically it is an abstract class which represents of buffer (the size is particular to implementation and can even be 0 for unbufferd stream buffers). The one for std::cout is written such that when it "overflows" it is flushed into stdout.
In fact, you can change the std::streambuf associated with std::cout (or any stream for that matter). This often useful if you want to do something clever like make all std::cout calls end in a log file or something.
And as dirkgently said you are confusing calling convention with other details, they are entirely unrelated to std::cout's buffering.
In addition, mixing output paradigms (printf and cout) are implementation specific.