This question already has answers here:
Pointer expressions: *ptr++, *++ptr and ++*ptr
(11 answers)
Closed 5 years ago.
If we have
int i = 5; /*line 1*/
int *p = &i; /*line 2*/
*p++; /*line 3*/
What is the order of evaluation for line 3?
(I know that after this p might point to something weird - but I'm not interested in the correct memory addressing but the order of evaluation, as both * and ++ seems to have same precedence)
No, postfix increment has higher precedence.
In your case, the side-effect of the increment will take place after the value evaluation note (with the dereference operator). The result of the value evaluation, though, is discarded (you did not make any effort to store the result).
So, finally, the result will be the equivalent as p++;
Note:
Quoting C11, chapter §6.5.2.4, (emphasis mine)
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented (that is, the value 1 of the appropriate type is
added to it). See the discussions of additive operators and compound assignment for
information on constraints, types, and conversions and the effects of operations on
pointers. The value computation of the result is sequenced before the side effect of
updating the stored value of the operand. [...]
*p++ is treated as *(p++) because precedence of postfix ++ is higher than *.
You have to put parenthesis around the *p for this to work:
int i = 5; /*line 1*/
int *p = &i; /*line 2*/
(*p)++; /*line 3*/
printf("Hello, World! %d\n", *p);
See: http://en.cppreference.com/w/c/language/operator_precedence
Related
Here is another naïve question from a C newbie: on this page, https://en.cppreference.com/w/c/language/operator_precedence, the precedence of the postfix increment is listed to be higher than that of pointer dereference. So I was expecting in the following code that the pointer is incremented first (pointing at 10) and then dereferenced.
#include <stdio.h>
int main()
{
int a[] = {3, 10, 200};
int *p = a;
printf("%d", *p++);
return 0;
}
However this code outputs still the first array item (3). What am I missing by the concept?
Precedence is placing of parenthesis.
The expression *p++ can be parenthesized as
(*p)++ // incorrect precedence
*(p++) // correct precedence
Note that the value of p++ is the value of p before any change, so the net effect of the correct precedence is the same as *p without ant reflection over the side-effect ++. The change to p itself does not alter the result of *(p++).
As you have correctly assumed, the expression *p++ is evaluated as *(p++); that is, the ++ operator has higher precedence than the * operator.
However, the value of the expression, p++, is just the value of p (i.e. its value before the increment). A side-effect of the operation is that the value of p is incremented after its value has been acquired.
From this Draft C11 Standard:
6.5.2.4 Postfix increment and decrement operators
…
2 The result of the postfix ++ operator is the
value of the operand. As a side effect, the value of the operand
object is incremented (that is, the value 1 of the appropriate type is
added to it). … The value computation of the result is sequenced
before the side effect of updating the stored value of the operand. With
respect to an indeterminately-sequenced function call, the operation of
postfix ++ is a single evaluation. …
Operator precedence specifies how an expression is parsed. Since postfix ++ has higher precedence than *, the expression is equivalent to *(p++). Rather than (*p)++ which would have given it a completely different meaning.
But just because this forces p++ to be evaluated first, it doesn't affect the characteristic of the ++ operator. The C language specifies this operator to behave as (from C17 6.5.2.4/2):
"The value computation of the result is sequenced before the side effect of
updating the stored value of the operand."
This means that p++ always gives the value of p before ++ is applied. In this case p is a pointer, so the value will be the address it pointed at prior this expression. So the code is completely equivalent to this:
int* tmp = p;
p++;
printf("%d", *tmp);
Precedence controls which operators are grouped with which operands. Postfix ++ having higher precedence than unary * simply means that *p++ is parsed as *(p++) instead of (*p)++.
*(p++) means you are dereferencing the result of p++. The result of p++ is the current value of p. As a side effect p is incremented. It is logically equivalent to
tmp = p;
printf( "%d\n", *tmp );
p = p + 1;
where the printf call and the update to p can happen in any order, even simultaneously (interleaved or in parallel).
As per C, PostIncrement(a++) > Dereference(*) > Assignment(=)
When I execute this below c snippet,
#include <stdio.h>
int main(){
int arr[]= {1,2,3};
int *p = a;
*p++ = 3;
for(int i=0;i<3;i++){
printf("%d ",arr[i]);
}
}
Output:
3 2 3
But if we apply order of precedence in this statement,
*p++ = 3;
The statement will be evaluated in the following order:
p++ will be evaluated
*p will get dereferenced.
then 3 will be assigned to *p using the assignment operator
If we apply the above order,
p which is pointing to the start of the array arr, will get incremented first and point to the second element of the array. Then second element's address will get dereferenced and then 3 will be assigned to the second index. So our expected output should be 1 3 3
But the output I got is 3 2 3.
I know that my expected output is not correct. It'll be helpful if you explain the order of evaluation here in this case of the output of the compiler.
Precedence only determines the grouping of operators with operands - it does not control the order in which expressions are evaluated. Precedence rules only determine that
*p++ = 3;
should parsed as
*(p++) = 3; // as opposed to (*p)++ = 3 or *(p++ = 3)
not that operations be executed in a specific order.
The ++ and –– operators have a result and a side effect. The result of postfix ++ is the current value of the operand; the side effect is to increment the operand. Your expression is logically equivalent to
tmp = p;
*tmp = 3;
p = p + 1;
with the caveat that the assignment to *tmp and the update of ptr can happen in any order, and they can even be interleaved or executed in parallel.
The result of a post-increment expression is the value of the operand before it is incremented. Thus, even though the ++ in *p++ does, indeed, have higher precedence than the *, the latter is applied to the result of the p++ expression which is, as just mentioned, the initial value of p.
According to the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the operand.
As a side effect, the value of the operand object is incremented (that
is, the value 1 of the appropriate type is added to it). See the
discussions of additive operators and compound assignment for
information on constraints, types, and conversions and the effects of
operations on pointers. The value computation of the result is
sequenced before the side effect of updating the stored value of the
operand. With respect to an indeterminately-sequenced function call,
the operation of postfix ++ is a single evaluation. Postfix ++ on an
object with atomic type is a read-modify-write operation with
memory_order_seq_cst memory order semantics.
Thus in this statement
*p++ = 3;
the expression p++ returns the current value of the pointer p that is a pointer that points to the first element of the array. It is this pointer to the first element of the array that is dereferenced.
So this statement
*p++ = 3;
is not equivalent to the statements
p++;
*p = 3;
"The statement will be evaluated in the following order:
p++ will be evaluated
*p will get dereferenced.
then 3 will be assigned to *p using the assignment operator"
Post Increments operator doesn't work like that. You can assume like this for better understanding.
When p++ gets evaluated, first, its present value is stored at a temporary location then the increment takes places.
All remaining operations are performed on the value stored in temporary location.
For subsequent statements incremented value is used.
running this code:
#include <stdio.h>
int main() {
int x[]={20,30};
int *p=x;
++*p++;
printf("%d %d\n",x[0],*p);
return 0;
}
the output is 21 30 which is something that doesn't make sense to me because according to C operator precedence the postfix increment comes first though if that was the case in my opinion the output should be 20 31.For the record i am new to programming and it really seems that i cant get the hang of it so sorry if this question is stupid :)
From the C++ Standard (the same is valid for the C Standard)
5.2 Postfix expressions
1 Postfix expressions group left-to-right.
Postfix expressions and p++ is a postfix expression have higher priority than unary expressions.
The C++ Standard
5.3 Unary expressions
1 Expressions with unary operators group right-to-left.
In this expression ++*p there are two unary subexpressions: *p and ++( *p )
So the whole expression can be written like
++( *( p++ ) );
Take into account regarding the postfix expression ++ that (now it is the C Standard)
6.5.2.4 Postfix increment and decrement operators
2 The result of the postfix ++ operator is the value of the operand.
As a side effect, the value of the operand object is incremented (that
is, the value 1 of the appropriate type is added to it).
Let's consider the result of the expression statement
++( *( p++ ) );
subexpression p++ has the value of its operand that is the address of type int * of the first element of the array. Then due to the dereferencing the expression *( p++ ) yields the lvalue of the first element of the array that is x[0] and then its value is increased. So the first element of the arry now has the value 21.
At the same time the postfix increment incremented the pointer p as its side effect (see the quote above from the C Standard). Its now points to the second element of the array.
Thus the output will be
21 30
You first increment where p points to and then you advance the pointer by one.
So, p points to 20, thus ++20 = 21.
Then the pointer will be increased by once, and due to pointer's arithmetic, it will point to next element of 20, which is 30, in your array.
As M.M said, you are confusing, the order of evaluation with precedence. Read more about it here.
according to C operator precedence the postfix increment comes first
Precedence is not the same thing as order of evaluation.
Precedence controls which operators are grouped with which operands. In this case, the expression ++*p++; is parsed as ++(*(p++)).
The order of evaluation is
Evaluate p++; the result of this evaluation is &x[0], and the side effect is to advance p to point to x[1];
Dereference the result of 1; the result of this evaluation is x[0];
Apply the prefix ++ operator to the result of 2; the result of this evaluation is x[0] + 1, with the side effect that the value stored in x[0] is incremented.
Remember that side effects do not have to be applied immediately upon evaluation; they may be deferred until a sequence point.
#include<stdio.h>
int main()
{
int a[2]={10,4};
int *k;
int *j;
j=a;
k=j;
printf("j=%d,k=%d\n\n",*j,*k);
*j++;
++*k;
printf("j=%d,k=%d",*j,*k);
return 0;
}
The output is:
j=10 k=10
j=4 k=11
I thought that it should have same result but this is not the case.
I wished to ask what is causing this difference. I didn't got the reason behind it.
You need to dig out your operator precedence table.
*p++ is evaluated as *(p++)
++*p is evaluated as ++(*p)
The second one is due to the prefix ++ having the same precedence as pointer dereference * so associativity (which is from right to left for those operators) comes into play.
For completeness' sake, *(p++) dereferences the current value of p, and p is increased by one once the statement completes. ++(*p) adds 1 to the data pointed to by p.
You have two things going on here:
The different semantics between prefix and postfix ++;
Different precedence of prefix and postfix operators.
Postfix operators have higher precedence than unary (prefix) operators, so the expression *p++ is parsed as *(p++) - you're applying the * operator to the result of p++. By contrast, the prefix ++ operator and unary * have the same precedence, so the expression ++*p is parsed as ++(*p) - you're applying the ++ operator to the result of *p.
Also remember that prefix and postfix ++ have slightly different behavior. Both increment their operand as a side effect, but the result of postfix ++ is the current value of the operand, while the result of prefix ++ is the value of the operand plus 1.
This question already has answers here:
Post-increment on a dereferenced pointer?
(13 answers)
Closed 8 years ago.
I'm not really sure what the order here is. Is it:
1) Dereference the value of pointer p after increasing it
2) Dereference the value of pointer p before increasing it
There is no ordering between the increment and the dereference. However, the * operator applies to the result of p++, which is the original value of p prior to the increment.
In the operators table, you can see that the suffix operator ++ have higher place than the * unary operator.
Hence, *p++ increase p (and not *p), and return the value of the address that p contained before the increment (since it's the suffix ++).
But the order is implementation-depend. It may begin by dereferencing p, and then increase it, and it may store the old value of p, increase it, and then dereference the old value.
Try it. The program
#include <stdio.h>
int main(void) {
int p[2];
int *q = p;
p[0] = 10;
p[1] = 100;
printf("%d\n", *q++);
printf("%d\n", *q);
return 0;
}
prints
10
100
showing that the ++ applies to p, not to *p, and that the increment happens after the dereference.
EDIT: (Thanks to #EricLippert for convincing me to pull out K & R)
Not only may there be a happens-after relationship, but according to K & R page 203, there must be:
A postfix expression followed by a ++ or -- operator is a postfix expression. The value of the expression of the expression is the value of the operand. After the value is noted, the operand is incremented (++) or decremented (--) by 1.
(emphasis mine)
Granted, I don't believe that K & R says anything about the semantics of C in the presence of multithreading (according to Wikipedia the pthreads specification was released in 1995), but for a single-threaded program K & R is pretty clear.
Given q = *p++;, q gets the value that p pointed to before the increment. Another way to say it is that the value of the expression *p++ is the value that p pointed to before being incremented.
The postfix ++ and -- operators essentially have higher precedence than the prefix unary operators. Therefore, *p++ is equivalent to *(p++); it increments p, and returns the value which p pointed to before p was incremented.
To increment the value pointed to by p, use (*p)++ (or perhaps ++*p, if the evaluation order of the side effect doesn't matter).