I stumbled upon https://en.cppreference.com/w/cpp/language/operator_precedence
On the chart, I see that post-increment operator (++) is way above assignment operator (=).
However, I know that
int a[] = {10,20};
int* b = &a[0];
*(b++) = 5;
cout << a[0] << endl; // 5
cout << a[1] << endl; // 20
cout << *b << endl; // 20, now points to a[1]
I always take it for grant that post-increment happens after the assignment operator. However, if I follow the operation precedence chart, then isn't post-increment suppose to happen before = operation? Isn't the answer suppose to be a={10, 5} rather than a={5, 20}?
"Precedence" is misleading. It has little to do in general with evaluation order (what happens first), but instead determines what is the operand of each operator for the purpose of evaluation. But let's examine your example.
*(b++) = 5;
This means that 5 is to be assigned to the lvalue on the left. And since C++17, we know that 5 is evaluated entirely before *(b++). Prior to that, they could be evaluated in any order.
Now, b++ has the meaning of "increment b, but evaluate to its previous value". So b++ may cause the increment to happen prior to the assignment taking place, yes, but the value of (b++) is the address before the increment happened. And that is why b is updated to point at the next element, while modifying the current one, in one expression.
Post increment (b++) increments b, then returns the previous value of b.
Pre increment (++b) increments b, then returns the new value of b.
To get the behavior you're expecting, change from post-increment to pre-increment.
For example:
#include <iostream>
int main() {
int a[] = {10, 20};
int *b = &a[0];
*(++b) = 5;
std::cout << a[0] << std::endl;
std::cout << a[1] << std::endl;
std::cout << *b << std::endl;
}
Yields the following output:
10
5
5
Table is Correct. And there is no confusion for the result.
Just remember the fact that post increment(PI) or decrement(DI), perform +1 or -1 update after the current statement containing PI or DI.
*(b++) = 5;
1st b++ will take place first as it is in parentheses. but b didn't move next yet. As compiler always remember in post operations that it would perform it after the current statement. so it is like:
*b = 5; // a[0]=5; compiler remembered b=b+1; to be executed.
so now b = b+1;
hence b is now pointing at a[1];
Related
My Code is:
int abdul = 11;
int *ptr = &abdul;
//Problem is here
// *ptr += 1;
// *ptr++;
cout << &*ptr;
cout << "\n" << &abdul;
cout << *ptr;
}
If I use *ptr +=1 it added 1 in abdul location value. But if I use *ptr++ it gives some random value.
When I use *ptr += 1 the output is correct. But using increment or decrement operator value gets wrong. I don't know where the problem is.
Due to operator precedence, *ptr++ is treated as *(ptr++). The pointer is incremented first and then dereferenced. In your case, that causes undefined behavior since ptr points to a single object.
To increment the value of the object that ptr points to, use (*ptr)++ or ++(*ptr).
It's better to be clear about your intention using parenthesis.
Operator precendece. *ptr++ is evaluated as *(ptr++). But you want (*ptr)++ Just add some parantheses to show the compiler what you want.
Due to the Operator Precedense what happens is you increment the address doing ptr++ and then you dereference it by doing *ptr.
what you can do is use prefix increment : ++*ptr
What is the order of evaluation in ++*ptr++? Does it change when pointers and lvalues are involved in the operation?
If the precedence of a++ is higher than *a or ++a, then why is ++*a++ evaluated as first returning the incremented value then changing the pointer, rather than changing the pointer, then incrementing the value at the location.
Refrence for Precedence: https://en.cppreference.com/w/cpp/language/operator_precedence
arr = {9, 99, 999 };
int *ptr = arr;
std::cout << ++*ptr++ << '\t';
std::cout << *ptr;
I expected the output to be 100 100, but the actual output was 10 99.
The postfix increment a++ increments the pointer ptr, but returns the copy of ptr before the operation (see difference between prefix/postfix).
So it can be rewritten (as noted in Quimby's answer) as ++(*(ptr++)) and goes like:
ptr++ : increments ptr so that it points to 99, but returns another pointer that still points to 9
*ptr++ : dereferences, evaluates to 9
++*ptr++ : increments the value pointed to by the copied pointer, meaning increments 9 and returns 10
Here the logic behind pre/post increment/decrement is explained well:
Pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.
Post-increment and post-decrement creates a copy of the object, increments or decrements the value of the object and returns the copy from before the increment or decrement.
From: https://en.cppreference.com/w/cpp/language/operator_incdec
Postfix operators have higher precedence that prefix so they BIND tighter/first so: ++*ptr++ is the same as ++(*(ptr++)) which boils down to what operand works on what. So postfix ++ will be applied to your 'ptr' pointer but 'after' first std::cout line. Prefix ++ will work on dereferenced ptr so this all is the same as:
int arr[] = {9, 99, 999 };
int *ptr = arr;
++(*ptr); // 9+1=10
std::cout << *ptr << '\t';
ptr++; // now ptr points to 99
std::cout << *ptr;
In short, because ++*ptr++ is rewritten as ++(*(ptr++))
The rules in the link are quite clear:
The postfix ++ has highest precedence => ++*(ptr++)
The prefix ++ and * have the same precedence and they are right-associative => ++(*(ptr++))
The expression can also be split into individual statements like this:
arr = {9, 99, 999 };
int *ptr = arr;
int *ptr2 = ptr++;//ptr2 still points to the first element
int val = *ptr2; // 9
int incVal= ++val; // 10
Hopefully it's clear that the ptr now points to the second element of the array and the result of the expression is the incremented value.
Since you are using a single dimensional array
++*ptr referred to increment in pointer ptr to 0 elements of array, after incrementing the output for this will be 10
The postfix ++ has highest precedence => ++*(ptr++)
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'm trying to understand how the parentheses affects the precedence in an expression:
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto b = arr;
std::cout << *(++b) << std::endl;
// output : 1
In this code I get the expected output but if I change it to:
std::cout << *(b++) << std::endl;
// output 0
I get 0 as output. Because of the parentheses I though b++ will be evaluated first and then de-referencing will occur. It seems I was wrong, then I removed the parentheses completely and test with *++b and *b++ and get the same results.Does that mean the parentheses don't affect the precedence on this kind of expressions ? And why are the results of this two expressions are equivelant:
*(b + 1)
*(++b)
But it's not the case with *(b++) ?
It does evaluate the b++ first. b++ increments b and returns the previous value of b, before the increment happened. The result of b++ and the value of b afterwards are different. Think of it as (using int instead of int * because a reference-to-pointer makes the signature ugly):
int postfix_increment(int &x) {
int result = x;
x = x + 1;
return result;
}
(Except that using the incremented value before the next sequence point is undefined behavior.)
If you introduce a temporary variable for the result of the parenthesis, to make sure it's evaluated first, it may be easier to see the difference:
int *tmp = b++;
// At this point, b == tmp + 1!
std::cout << *tmp << std::endl;
*(b++) is equivalent to storing the old pointer, incrementing the pointer and dereferencing the old pointer
int* post_increment(int* b)
{
int* old = b;
++b;
return old;
}
It is an instructive exercise to write a thin iterator wrapper around a plain pointer. When writing user-defined iterators, the above post_increment() function is usually written an overloaded operator++(int). The int argument is purely to distinguish it from the pre-increment operator operator++(). In addition, you'd need an overloaded operator*() to dereference an iterator.
*(b+1) works because you do math. Math takes parentheses into account. Only after Math is done, the expression gets evaluated.
*(++b) works because you increment before evaluation (prefix increment).
*(b++) doesn't work because you increment after evaluation (postfix increment).
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