Consider the code:
#include<iostream>
using namespace std;
int refcube(double &ra)
{
ra*=ra*ra;
return ra;
}
int main()
{
auto x=2.0;
cout<<"cube of "<<x<<" is "<<refcube(x)<<endl;
return 0;
}
The output is:
cube of 8 is 8
Why the value of x at the first is displaying as 8 instead of 2?
Because evaluation order is not specified.
The compiler may generate the code to call refcube(x) and compute its value before or after generating the code to obtain the value of x, for output to std::cout.
Your compiler chose to compile this C++ code as calling refcube(x) first, and then by evaluating x.
The C++ language specification spends quite a few pages on the topic of "sequencing", which (very loosely speaking) specifies the evaluation order. To make a long story short, in this example, x is not sequenced with respect to refcube(x), in the expression that generates the output to std::cout, and such a compiler is free to compile either portion of the expression first.
Related
I have recently taken up studying algorithms and data structures.I came across fibonacci problem and its solution using recursion. But thats the thing. I understand how recursive calls work when there is only one(like in factorial of a number).The function calls keep on stacking up until they hit the base case and then they start unraveling by one to the desired answer.
But What I dont get is how does recursion work when there are two recursive calls in an expression like f(n)+f(n/2). I mean which call is resolved first and when does the second call gets resolved. Also how is the sum calculated if this expression is assigned to a statement?
I wrote a small code to decipher this myself.
#include <iostream>
#include <string>
int main()
{
int recursionTest(int n, char c);
int x;
std::cin>>x;
std::cout<<"Ans:"<<recursionTest(x,'c');
}
int recursionTest(int n,char c)
{
int result=0;
if(n==0)
return 1;
std::cout<<n<<":"<<c<<std::endl;
result=recursionTest(n/2,'L')+recursionTest(n/3,'R');////I cant figure
out the flow of
control here!!!
return result;
}
And I got the following output.
24
24:c
12:L
6:L
3:L
1:L
1:R
2:R
1:L
4:R
2:L
1:L
1:R
8:R
4:L
2:L
1:L
1:R
2:R
1:L
Ans:20
SO I get it ,its a tree structure. But I still dont know how we are getting 20 as answer(input=24). How is the sum expression working and what is it summing,how can I look at the tree structure and generate the same out put?
There is no defined order to how the two subexpressions of the + operator are evaluated. The compiler can emit code to evaluate either one first and the other one second. It can even interleave some computations of one side with computations of the other. For example, it could calculate n/3, then n/2, then the right function call, and finally the left function call.
The flow control is just like for a single case of recursion followed by another single case. So, your line:
result=recursionTest(n/2,'L')+recursionTest(n/3,'R');
is effectively the same as:
int left = recursionTest(n/2,'L');
int right = recursionTest(n/3,'R');
result = left + right;
except for the implication in my version that the left function call is guaranteed to be evaluated before the right function call.
Here operator precedence will play the role
f(n) + f(n/2);
In the above code snippet f(n) will get called first and then f(n/2). basically arithmetic operators compile from left to right.
If you want to debug the code use printf statements inside function f(int) by printing n value . By this you can get the hang of the code
Consider the following c++ code for a simple binary tree DFS traversal:
#include <iostream>
#include <vector>
using namespace std;
int print_vector(vector<char> *vec){
for (auto &it: *vec)
cout<<it;
cout<<'\n';
return 0;
}
int btree_dfs_traversal(int max_depth, int cur_depth, vector<char> position){
if (cur_depth>max_depth)
return 0;
print_vector(&position);
vector<char>left = position;
vector<char>right = position;
left.push_back('l');
right.push_back('r');
return btree_dfs_traversal(max_depth, cur_depth+1, left)+btree_dfs_traversal(max_depth, cur_depth+1, right);
}
int main(int argc, const char * argv[]) {
vector<char> pos;
btree_dfs_traversal(4, 0, pos);
return 0;
}
The function(a minimal example) visits a binary tree, and prints the "position" of each node it visits. The only difference with a standard DFS is that (this part made the difference), most implementation uses a iteration for visiting the two nodes, while my the return statement returns the sum of two visits.
I expected the program to recurse from the left statement, i.e. the output starts with l, ll, lll, ... And indeed in my system(OSX) it is like this, and ideone has this output too.
However, in some friends' system, the output is different. The recursion starts from the right statement, i.e. r, rr... Unfortunately, I do not have exact information of their complier information at present.
My question is: is the sum of two recursion being a undefined behavior such that different compiler can produce different results? Or, it is just wrong to start from right?
The "problem" is that in f(1) + f(2) it is unspecified which function call comes first. Different compilers will pick different order and the order can depend on any number of unrelated factors. From the C++ reference:
Order of evaluation
Order of evaluation of the operands of almost all C++ operators (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. The compiler can evaluate operands in any order, and may choose another order when the same expression is evaluated again.
There are exceptions to this rule which are noted below.
Except where noted below, there is no concept of left-to-right or right-to-left evaluation in C++. This 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.
See http://en.cppreference.com/w/cpp/language/eval_order for exceptions and more info.
I saw this piece of code today:
while(scanf("%d %d",&x,&y),x||y)
{
....
From what I've understand, it enters the loop if some of the values (x or y) is true.
Since the scanf docs says:
On success, the function returns the number of items of the argument
list successfully filled. This count can match the expected number of
items or be less (even zero) due to a matching failure, a reading
error, or the reach of the end-of-file.
I have rewritten the code to:
while(scanf("%d %d",&x,&y) >= 1)
{
....
But on an online programming challenge site the first while works, the second fails.
Am I right on my assumptions ? What are the differences between this two pieces of code?
(I am tagging as C++, because I have tested in C++ 4.8.2 - GNU C++ Compiler)
scanf returns the number of arguments it matches, but the first code fragment throws out that result and just checks to see if either x or y is true. The second fragment returns that you matched at least one integer, regardless of value.
Consider the input "0 0". In the first case, scanf() returns 2, but x || y returns false. In the second case, your conditional is true.
The first code gives while the result of x||y, this is correct
However, the second code compares the return value of scanf and 1, and then gives while the comparing result.
run this code and you'll be clear.
#include<stdlib.h>
#include<iostream>
using namespace std;
int main()
{
int x, y;
cout<<(scanf("%d %d", &x, &y), x||y)<<endl;
cout<<(scanf("%d %d", &x, &y))<<endl;
return 0;
}
In the section of the code below, there is no return statement in the function but it still compiled and gave the right answer. Is this a normal behavior?
#include <iostream>
int multiply (int x, int y) {
int product = x * y;
}
int main (int argc, char **argv) {
std::cout << multiply(4, 5) << std::endl;
return 0;
}
No, getting the correct answer from the function is not normal behaviour, it's a coincidence. You should not rely on this.
From C++03, 6.6.3 The return statement /2 (and the same section for C++11 as well):
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
You'll probably find that you're getting the correct answer simply because of the side effects of your calling convention.
For example, if a function value is returned in the (mtyhical) r0 register, it may be that the calculation uses that register within the function to hold the value, before storing it into the memory representing the product variable. So the fact it's in r0 when you return is just a hang-over from the way things are done.
Compiling with different levels of optimisation, or using another compiler, or even compiling on a Tuesday evening during a blue moon may affect the outcome, that's the main problem with undefined behaviour - it's untrustworthy. At a bare minimum, a good compiler would have warned you about this.
Again, a silly question.
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int i = 0;
i = i++;
cout<<i;
return 0;
}
I get 1 printed as a result of this program though I expected 0: first a temp object created eing equal 0, then i is incremented, then temp object is returned and assigned to i. Just according to:
5.2.6 Increment and decrement [expr.post.incr]
1 The value obtained
by applying a postfix ++ is the value
that the operand had before applying
the operator. [Note: the value
obtained is a copy of the original
value ]
I checked it under MS VC 2008 and GCC. They give both the same result, though at least gcc issues a warning in incrementation string. Where am I wrong?
The behavior of
i = i++;
is undefined. If a single expression assigns two different values to a variable, the C++ spec says that anything can happen - it could take on its old value, one of the two new values, or pretty much anything at all. The reason for this is that it allows the compiler to make much more aggressive optimizations of simple expressions. The compiler could rearrange the order in which the assignment and ++ are executed, for example, if it thought it were more efficient.