Precedence of postfix ++ - c++

Consider these codes:
int a = 5;
int b = a++;
cout << "b is " << b << endl; // b is 5
or:
int get_number(){
int a = 5;
return a++;
}
int main(){
int b = get_number();
cout << "b is " << b << endl; // b is 5
}
According to this table postfix ++ operator has higher precedence than = operator so the output should be b is 6. but the output is b is 5. How can we explain this?

The contract of the postfix++ operator (and postfix-- operator) for built-in types is that it returns the previous value, irrespective of the change that takes place. So the function still returns 5, even if the variable which received the change is assigned 6 afterwards.

As per expr.post.incr, emphasis mine:
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 ]
The value computation of the ++ expression is sequenced before the
modification of the operand object. With respect to an
indeterminately-sequenced function call, the operation of postfix ++
is a single evaluation
int a = 5;
int b = a++; // the value computation for a is
// the non-modified / non-incremented value
// which is 5
std::cout << "a is " << a << std::endl; // a is 6
std::cout << "b is " << b << std::endl; // b is 5

Related

Why does the fist print statement of b in the function print 5 and not 6? [duplicate]

This question already has an answer here:
The Definitive C++ Book Guide and List
(1 answer)
Closed 2 years ago.
I'm confused. I would expect that the first print statement in the function would print 6 and not 5. Because a++ + c++ = (1+1) + (3+1) = (2+4 = 6).
#include <iostream>
#include <string>
int main()
{
int a = 1;
int b = 2;
std::cout << "intitialisation b:"<< b << std::endl;
int c = 3;
{
auto b = ++a + c++;
std::cout << "increment b in function:" << b << std::endl;
auto e = b;
c += ++b;
std::cout << "increment b in function:" << b << std::endl;
}
std::cout << "increment b out function:" << b << std::endl;
int* p = &a;
int* q = &b;
std::cout <<"value pointer:" << *q << std::endl;
++(*q);
std::cout <<"value pointer:" << *q << std::endl;
*p += a++ + (*p)++;
}
intitialisation b:2
increment b in function:5
increment b in function:6
increment b out function:2
value pointer:2
value pointer:3
Nadine
The behaviour of the statement
*p += a++ + (*p)++;
is undefined. That's because you have simultaneous reads and writes to a (sometimes via the pointer) in an unsequenced step.
That means that the entire program is undefined, somewhat paradoxically perhaps, including any statements that, conceptually speaking, have already been ran prior to that one. And that includes the specific statement you're asking about!
Setting that aside, ++a evaluates to the incremented value of a, c++ evaluates to the unincremented value of c. So if there were no undefined constructs in your code, the output would be 2 + 3 which is 5.

Operator overloading returning a reference

I am trying to understand what is the real deal with returning a reference, while studying operator overloading. I create this very simple problem:
#include <iostream>
using namespace std;
class mydoub {
public:
double pub;
mydoub(double i = 0) : pub(i) {}
};
mydoub &operator += (mydoub &a, double b) {
a.pub = a.pub+b;
return a;
}
int main() {
mydoub a(5), b(6);
cout << "1: " << a.pub << " " << b.pub << endl; // expected output 1: 5 6
b = a+= 7;
cout << "2: " << a.pub << " " << b.pub << endl; // expected output 2: 12 12
b.pub = 8;
cout << "3: " << a.pub << " " << b.pub << endl; // unexpected output: 3: 12 8
}
The output is:
1: 5 6
2: 12 12
3: 12 8
which is quite unexpected to me. In fact, b has been assigned a reference to a, right after the latter has been modified, so I expect b.pub=8 to act on a as well, as a result of the reference passing through the operator +=. Why isn't it so? What is then the difference with a non-reference overload, say mydoub operator += ( ..?
You are messing with an understanding of reference. Reference, in fact, is just dereferenced pointer and when you do b = a, it is actually copying the a value to b, they are not pointing to the same object. To point to the same object you need to use pointers or make b not mydoub type, but mydoub& type (in that case, while initializing you can point to the same object).
mydoub& operator += is used to can modify the result of += operator. For example,
mydoub a = 1;
++(a += 3)
After that a will 5, but if you use mydoub operator += it will be 4.

Precedence of operators?

Look at this simple class:
class A {
int *val;
public:
A() { val = new int; *val = 0; }
int get() { return ++(*val); }
};
Why when I run this code it prints 21:
int main() {
A a, b = a;
cout << a.get() << b.get();
return 0;
}
But if I run it like this it prints 12 which is what I was expecting:
int main() {
A a, b = a;
cout << a.get();
cout << b.get();
return 0;
}
What am I missing here? Operator precedence? FYI, this is a C++ test problem, not a production code.
EDIT:
Does it means that when I have cout << (Expr1) << (Expr2) then Expr1 and Expr2 are evaluated before the output of Expr1 is printed?
Operator precedence does not dictate the order of evaluation of intermediate results. I.e. it does not dictate the order of evaluation of sub-expressions in the entire expression.
Expression statement
cout << a.get() << b.get();
can be executed by the compiler as
int tmp_a = a.get();
int tmp_b = b.get();
cout << tmp_a;
cout << tmp_b;
or as
int tmp_b = b.get();
int tmp_a = a.get();
cout << tmp_a;
cout << tmp_b;
In this case operator precedence and associativity for operator << guarantees that tmp_a is sent to output before tmp_b. But it does not guarantee that tmp_a is evaluated before tmp_b.
This line:
cout << a.get() << b.get();
does not specify whether a.get() or b.get() is evaluated first.
Since a and b share the same val pointer, the order of those operations affect the output.
(Edit)
Does it means that when I have cout << (Expr1) << (Expr2) then Expr1 and Expr2 are evaluated before the output of Expr1 is printed?
That is also not specified.

Strange output, not as expected

sorry for asking you a stupid question, but I just can't figure out why I keep on getting this output.
So here is my code:
#include <cstdio>
#include <iostream>
using namespace std;
unsigned n = 4242;
int getRemainderOf(int m, int n, int& quotient);
static int l = 0;
int main()
{
int quotient; // the value of which should be changed after calling the func.
for(int i=-1; i<=1; ++i)
{
for(int j=-1; j<=1; ++j)
{
if( i && j )
{
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) << " " << quotient <<endl;
cout << "("<< i*7 << "," << j*3 << ") " << getRemainderOf(i*7, 3*j, quotient) << " "; cout << quotient <<endl;
}
}
}
return 0;
}
int getRemainderOf(int m, int n, int& quotient)
{
++l;
cout << l <<endl;
quotient = m / n;
cout << " quotient " << quotient <<endl;
return m % n;
}
so what I expected to see in the first line of my output was the remainder and then the quotient that I get after calling the function getRemainderOf(). But instead when I cout the value of quotient like that I see that the value of quotient is a garbage value. So the value of the variable is not changed even though I've passed it to the function by using reference.
The funny thing is that if I cout the remainder (got by calling the function) and the quotient separately I will get it right.
I see that the problem might be in calling the function as a argument of the operator << function but I don't get it why the value of the quotient isn't changed since I call the function before I output it. This operator's associativity is left-to-right so what's wrong?
So could you please tell me what is the reason of this output.
What you've just found is a classic example of one of the quirks of C++. Your program can actually be decomposed into this simple example:
int i = 10;
f(i, ++i);
The compiler has the choice of function argument evaluation from left-to-right, but this is not guaranteed. Here's some standard text:
5.2/4 Postfix Epressions [expr.post]
When a function is called, each parameter shall be initialized with its corresponding argument. [Note: Such initializations are indeterminatly sequenced with respect to each other (1.9) - end note]
Because they are indeterminatly sequenced, the compiler has the freedom of evaluating ++i before the first argument and initializing it with the corresponding function parameter, and then evaluating i and initializing it with its respective parameter next.
The reason function call argument evaluation ambiguity is applicable here is because operator<<() is a function but it's just being called with the operator syntax. For example, this is what your code looks like if we use the operator-id syntax:
std::operator<<(std::operator<<(std::operator<<(std::cout, "(").operator<<(i*3), ",").operator<<(j*7), ")").operator<<(getRemainderOf(i*3, 7*j, quotient)).operator<<(quotient);
These are just chains of function calls with arguments and they obey the same rule as the one above.
The solution is to sequence the act of modifying the object and using it in the operator<<() call. You already achieved this with partitioning the operator<<() call into two statements with the semicolon ;, so the function is guaranteed to be called before quotient is printed.
The order of evaluation of function arguments is unspecified.
In these statements
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) << " " << quotient <<endl;
cout << "("<< i*7 << "," << j*3 << ") " << getRemainderOf(i*7, 3*j, quotient) << " "; cout << quotient <<endl;
there are called overloaded operators << that are in fact functions. You have to split each statement in two statements. For example
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) ;
cout << " " << quotient <<endl;

Pre / Post Increment Explanation

Please be easy on me and don't shoot me as I'm still newbie.
I'm totally confused and can't for life figure out why when I run this code:
int y = 9;
cout << "++y = " << ++y << "\n--y = " << --y << "\ny++ = " << y++ << "\ny-- = " << y-- << "\n";
cout << "y = " << y << "\n";
I get the following results:
y = 9
++y = 9
--y = 9
y++ = 8
y-- = 9
y = 9
instead of these results:
y = 9
++y = 10
--y = 9
y++ = 9
y-- = 10
y = 9
That I get from this code:
int y = 9;
cout << "y = " << y << "\n";
cout << "++y = " << ++y << "\n";
cout << "--y = " << --y << "\n";
cout << "y++ = " << y++ << "\n";
cout << "y-- = " << y-- << "\n";
cout << "y = " << y << "\n";
Can anyone explain -in simple words as possible- what happens in the first code so that it prints the result that way?
A simple rule is that you are not expected to increment the same location more than once in any given statement. So you should not code cout << y++ << ++y << endl; which contain two increments of y (assuming an int y; declaration).
For details, read about sequence points and undefined behavior in the C++ standard.
There are lot of related questions. Look into them for more!
When according to the rules operation * is to be counted before +, and ++ before *, it will be so.
a*b++ + c // first b++ (returns **old** b), than a*b, than ...+c
But when you have a++ * a--, nobody can tell, what of the two operands, a++ or a-- will be evaluated the first. According to ANSII standard, even if you use the same translator, the result is every time unpredictable.
cite from the C++ ANSII standard:
Except where noted, the order of evaluation of operands of individual
operators and subexpressions of individual expressions, and the order
in which side effects take place, is unspecified. Between the previ-
ous and next sequence point a scalar object shall have its stored
value modified at most once by the evaluation of an expression. Fur-
thermore, the prior value shall be accessed only to determine the
value to be stored. The requirements of this paragraph shall be met
for each allowable ordering of the subexpressions of a full expres-
sion; otherwise the behavior is undefined. [Example:
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // `i' becomes 9
i = ++i + 1; // the behavior is undefined
i = i + 1; // the value of 'i' is incremented
Sequence points:
at the end of the evaluation of a full expression (a full expression is an expression statement, or any other expression which is not a subexpression within any larger expression);
at the ||, &&, ?:, and comma operators;
and at a function call (after the evaluation of all the arguments, and
just before the actual call).
So, || is a sequence point, but << is not.
Mulitiline version of first code should be:
y = 9;
cout << "y-- = " << y-- << "\n";
cout << "y++ = " << y++ << "\n"
cout << "--y = " << --y << "\n"
cout << "++y = " << ++y << "\n"
cout << "y = " << y << "\n";