I have 2 questions.
consider this code:
int x=1,y=2;
int z =(x++)+(++y);
int w = (++x)++;
cout << z << "\t" << w << "\t" << x;
Now, this gives me 4, 3 and 4 and I'm guessing that w=3is because this int w = (++x)++ is undefined behavior, and that's fine with me. What I don't understand is this: I tried to write this line int w = (++x)++; like this int w = ++x++; and got error: lvalue required as increment operand, but, I saw here that postfix takes precedence over prefix, so why the isn't the postfix increment done, returns the variable and then increments it with the prefix? (as it is done when I use bracket)
Now back to this line: int z =(x++)+(++y). I tried to write it like int z =x+++++y and that didn't work - same error. Then I tried int z =x+++(++y) and it was fine, so what I think happened is this:
x++
++y
addition
but if I'm correct, why the brackets were needed? this is the way it should be by precedence
so why the isn't the postfix increment done, returns the variable
The postfix version doesn't return a reference, it returns a value - and the prefix increment can only work with a reference.
By adding brackets, you've changed the order of evaluation.
It is not an issue of precedence, but the way compiler parses the code.
To compile correctly you don't need to use brackets. Will work fine with spaces.
Related
Why does that code does not compile due to an error:
#include <iostream>
using namespace std;
int main()
{
int i = 0;
cout << ++(i++) << " " << i << endl;
return 0;
}
While that code does compile:
#include <iostream>
using namespace std;
int main()
{
int i = 0;
cout << (++i)++ << " " << i << endl;
return 0;
}
I do not understand that. From my point of view it would be pretty reasonable for the first chunk to compile. The expression ++(i++) would just mean take i, increment it and output, then increment it again.
I am not asking about an undefined behavior in int overflow. I do not know about r and l value at all at the time of writing the question and I do not care why is ++i considered an l-value, but i++ is not.
This is because the post increment and pre increment operators return values with different types. Result of post increment is a so-called 'rvalue', meaning it can not be modified. But pre-increment needs a modifiable value to increment it!
On the other hand, result of pre-increment is an lvalue, meaning that it can be safely modified by the post increment.
And the reason for above rules is the fact that post-increment needs to return a value of the object as it was before increment was applied. By the way, this is why in general case post-incrememts are considered to be more expensive than pre-increments when used on non-builtin objects.
Shortly speaking the difference is that in C++ you may use any even number of pluses (restricted only by the compiler limits) for the prefix increment operator like this
++++++++++++++++i;
and only two pluses for the post increment operator
i++;
The postfix increment operator returns a value (The C++ Standard, 5.2.6 Increment and decrement)
1 The value of a postfix ++ expression is the value of its
operand. [ Note: the value obtained is a copy of the original value
—end note ]
While the prefix increment operator returns its operand after increment (The C++ Standard ,5.3.2 Increment and decrement)
1 ...The result is the updated operand; it is an lvalue...
Opposite to C++ in C you also can apply only two pluses to an object using the prefix increment operator.:) Thus the C compiler will issue an error for such an expression like this
++++++++++++++++i;
When you compile it with clang you get error message that says it all.
<source>:8:13: error: expression is not assignable
cout << ++(i++) << " " << i << endl;
Maybe it is good to start with ++ operator. In fact it is shorthand for i = i + 1. Now if we look at postfix version i++, it says in standard that it returns copy of original value and as side efect it increments original value.
So from (i++) you get rvalue and are trying to assign to it and as we know you can't assign to rvalue.
I was writing this program
int x = 10;
int *yptr;
yptr = &x;
cout << "The address yptr points to = " << yptr;
cout << "The contents yptr points to =" << *yptr ;
(*yptr)++ ;
cout << "After increment, the contents are: " << *yptr;
cout << "The value of x is = " << x ;
Value increased of x from 10 to 11.
But when I write
*yptr ++ ;
Value did not increase, why?
In C++ language the grouping between operators and their operands is defined by the grammar. For convenience, this grouping is often expressed in simplified linear form called operator precedence. In C++ postfix operators have higher precedence than prefix/unary ones. So, in your case *yptr++ stands for *(yptr++), since postfix ++ has higher precedence than unary *. The ++ operator is applied directly to yptr and * is applied to the result of yptr++.
When you added the extra (), you completely changed the expression and re-grouped the operators and operands. In (*yptr)++ you forcefully associated the * with yptr. Now, * operator is applied directly to yptr and ++ is applied to the result of *yptr. Hence the change in the behavior.
In other words, the answer to your "why?" question is: because you explicitly asked the compiler make that change. The original expression was equivalent to *(yptr++) and you changed it to (*yptr)++. These are two completely different expressions with completely different meanings.
P.S. Note that the sequencing rules of C++ language does not generally allow one to describe the behavior of built-in operators in therms of what is evaluated "first" and want is evaluated "next". It is tempting to describe behavior of these expressions in therms of "++ works first, * works next", but in general case such description are incorrect and will only lead to further confusion down the road.
When you write (*yptr)++ first (*yptr) is fetched because () has higher precedence than ++, which is 10 and then ++ operator is applied, resulting 11. When you write *y ++;, first y++ is evaluated as ++ has higher precedence. That means the address is increased, then the content is fetched for * operator instead of incrementing the content. Learn operator precedence
(*ptr)++ increment the value that saved into ptr.
Like this
int *ptr;
*ptr =1;
(*ptr)++;
std::cout<< *ptr; //out put will be 2
BUT
*ptr++ increment the address of the usually for char pointer variables.
Like this
char *ptr = "Hello";
while(*ptr++)
std::cout<<*ptr; //out put will be ello
I am from C background, and now I am learning OOP using C++
Below is a program that calculates factorial.
#include <iostream>
using namespace std;
void main ()
{
char dummy;
_int16 numb;
cout << "Enter a number: ";
cin >> numb;
double facto(_int16);
cout << "factorial = " <<facto(numb);
cin >> dummy;
}
double facto( _int16 n )
{
if ( n>1 )
return ( n*facto(n-1) );
else
return 1;
}
The above code works fine.
But if I replace the return statement
return ( n*facto(n-1) );
with this
return ( n*facto(n--) );
then it doesn't work. The n-- won't decrement n by 1. Why?
I am using Visual Studio 2012
Edit:Got it! thanks :)
*also, I would like to add to the answers below: using --n will cause the n to decrement before the statement is executed. So, due to pre-decrement, the expression will become (n-1)*facto(n-1) . That is why it is better not to use pre-decrement in this case *
Currently, by using n-- you are passing the original and therefore unmodified value of n into facto which is causing a loop.
You need to use n - 1 instead. It would, on the face of it, be tempting to use --n since that would decrement n and evaluate to the new (lower) value. But --n will give you undefined behaviour since you are pre-multiplying the function return value by n and since * is not a sequence point, the value of n is not well-defined.
(By the way, the behaviour in C would have been identical).
[Edit: acknowledge Mike Seymour on the undefined behaviour point].
EDIT:: The explanation below is only to shed light on the usage of Post and Pre-Decrement for OP's better understanding of them. The correct answer for OP's code is, n*facto(n - 1). #OP: You should not do any pre-drecrement in that part of your code because it will invoke Undefined Behavior due to unsequenced modification of variable n.
Pre And Post-Decrement::
You have to use pre-decrement (wiki-link) if you want to decrement the variable before the value is passed. On the other hand, a post-decrement evaluates the expression before the variable is decremented:
int n = 10, x;
x = --n; // both are 9
and
int n = 10, x;
x = n--; // x = 10, i = 9
Why not to use pre-decrement in your case?:: n*facto(n--) causes UB.
Why?
The Standard in §5/4 says
Between the previous and next sequence point a scalar object shall
have its stored value modified at most once by the evaluation of an
expression.
and
The prior value shall be accessed only to determine the value to be
stored.
It means, that between two sequence points a variable must not be modified more than once and, if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.
return ( n*facto(n--) );
You are using the post decrement operator.
What happens is, You pass the value of n to the function and then decrement it. That doesn't affect the value that is already passed to the function
I came across this bit of code in an example from the Boost documentation:
std::vector<int> input;
input += 1,2,3,4,5,6,7,8,9;
How cute. Boost has a template for operator+= that takes advantage of the fact that the comma is, under most circumstances, an operator. (Wisely, C++ does not allow a hackist to overload "operator,".)
I like to write cute code too, so I played around some with the comma-operator. I found something that looks weird to me. What do you think the following code will print?
#include <iostream>
int main() {
int i;
i = 1,2;
std::cout << i << ' ';
i = (1,2);
std::cout << i << std::endl;
}
You guessed it. VC++ 2012 prints "1, 2". What's up with that?
[Edit: I should have been more precise. Should have said C++ does not allow operator "," in a list of int's to be overloaded. Or better yet, nothing. The ',' operator can be overloaded for classes and enums.]
CASE 1:
i = 1,2;
= has higher precedence than ,
hence, 1 is assigned to i.
Since assignment evaluates to an lvalue in c++,(evaluates to rvalue in c) it becomes i,2 which evaluates to2 (refer NOTE)
CASE 2:
i = (1,2);
() has higher precedence than =
expressions or operands separated by , operator evaluates to the value of the last expression or operand hence, 2 is assigned to i
NOTE
a comma expression like 33,77,x,y,z is evaluated from left to right.
The result of such comma expression is the value of rightmost expression .
Examples
Consider, int z=100;
then
1,4,5; //evaluates to 5
1,100,z+100; //evaluates to 200
Simple: "=" has higher precendence.
i = 1,2;
Is like (i=1),2, meaning the result of the expression is 2 but it's discarded.
i = (1,2);
The result of (1,2) is 2.
EDIT: this might be so things like
for (i=0, j=0; ...)
work as expected.
I'm a TA for an intro C++ class. The following question was asked on a test last week:
What is the output from the following program:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x) << endl << myFunc(x) << endl;
}
The answer, to me and all my colleagues, is obviously:
8
27
64
But now several students have pointed out that when they run this in certain environments they actually get the opposite:
64
27
8
When I run it in my linux environment using gcc I get what I would expect. Using MinGW on my Windows machine I get what they're talking about.
It seems to be evaluating the last call to myFunc first, then the second call and then the first, then once it has all the results it outputs them in the normal order, starting with the first. But because the calls were made out of order the numbers are opposite.
It seems to me to be a compiler optimization, choosing to evaluate the function calls in the opposite order, but I don't really know why. My question is: are my assumptions correct? Is that what's going on in the background? Or is there something totally different? Also, I don't really understand why there would be a benefit to evaluating the functions backwards and then evaluating output forward. Output would have to be forward because of the way ostream works, but it seems like evaluation of the functions should be forward as well.
Thanks for your help!
The C++ standard does not define what order the subexpressions of a full expression are evaluated, except for certain operators which introduce an order (the comma operator, ternary operator, short-circuiting logical operators), and the fact that the expressions which make up the arguments/operands of a function/operator are all evaluated before the function/operator itself.
GCC is not obliged to explain to you (or me) why it wants to order them as it does. It might be a performance optimisation, it might be because the compiler code came out a few lines shorter and simpler that way, it might be because one of the mingw coders personally hates you, and wants to ensure that if you make assumptions that aren't guaranteed by the standard, your code goes wrong. Welcome to the world of open standards :-)
Edit to add: litb makes a point below about (un)defined behavior. The standard says that if you modify a variable multiple times in an expression, and if there exists a valid order of evaluation for that expression, such that the variable is modified multiple times without a sequence point in between, then the expression has undefined behavior. That doesn't apply here, because the variable is modified in the call to the function, and there's a sequence point at the start of any function call (even if the compiler inlines it). However, if you'd manually inlined the code:
std::cout << pow(x++,3) << endl << pow(x++,3) << endl << pow(x++,3) << endl;
Then that would be undefined behavior. In this code, it is valid for the compiler to evaluate all three "x++" subexpressions, then the three calls to pow, then start on the various calls to operator<<. Because this order is valid and has no sequence points separating the modification of x, the results are completely undefined. In your code snippet, only the order of execution is unspecified.
Exactly why does this have unspecified behaviour.
When I first looked at this example I felt that the behaviour was well defined because this expression is actually short hand for a set of function calls.
Consider this more basic example:
cout << f1() << f2();
This is expanded to a sequence of function calls, where the kind of calls depend on the operators being members or non-members:
// Option 1: Both are members
cout.operator<<(f1 ()).operator<< (f2 ());
// Option 2: Both are non members
operator<< ( operator<<(cout, f1 ()), f2 () );
// Option 3: First is a member, second non-member
operator<< ( cout.operator<<(f1 ()), f2 () );
// Option 4: First is a non-member, second is a member
cout.operator<<(f1 ()).operator<< (f2 ());
At the lowest level these will generate almost identical code so I will refer only to the first option from now.
There is a guarantee in the standard that the compiler must evaluate the arguments to each function call before the body of the function is entered. In this case, cout.operator<<(f1()) must be evaluated before operator<<(f2()) is, since the result of cout.operator<<(f1()) is required to call the other operator.
The unspecified behaviour kicks in because although the calls to the operators must be ordered there is no such requirement on their arguments. Therefore, the resulting order can be one of:
f2()
f1()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or:
f1()
f2()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or finally:
f1()
cout.operator<<(f1())
f2()
cout.operator<<(f1()).operator<<(f2());
The order in which function call parameters is evaluated is unspecified. In short, you shouldn't use arguments that have side-effects that affect the meaning and result of the statement.
Yeah, the order of evaluation of functional arguments is "Unspecified" according to the Standards.
Hence the outputs differ on different platforms
As has already been stated, you've wandered into the haunted forest of undefined behavior. To get what is expected every time you can either remove the side effects:
int myFunc(int &x) {
int temp = x * x * x;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x+1) << endl << myFunc(x+2) << endl;
//Note that you can't use the increment operator (++) here. It has
//side-effects so it will have the same problem
}
or break the function calls up into separate statements:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
}
The second version is probably better for a test, since it forces them to consider the side effects.
And this is why, every time you write a function with a side-effect, God kills a kitten!