What happens when you dereference a postincrement C - c

I am receiving a lot of conflicting answers about this. But as I always understood it.
When we have a pointer in C and use it in a post increment statement, the post increment will always happen after the line of code resolves.
int array[6] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *p++); // This will output 0 then increment pointer to 1
output :
0
Very simple stuff. Now here's where I am receiving a bit of dissonance in the information people are telling me and my own experience.
// Same code as Before
int array[0] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *(p++)); // Issue with this line
output :
0
Now when I run that second version of the code The result is that it will output 0 THEN increments the pointer. The order of operations implied by the parentheses seems to be violated. However some other answers on this site tell me that the proper thing that should happen is that the increment should happen before the dereference. So I guess my question is this: Is my understanding correct? Do post increment statements always execute at the end of the line?
Additional Info:
I am compiling with gcc on linux mint with gcc version ubuntu 4.8.4
I have also tested this on gcc on debian with version debian 4.7.2

OP's "The result is that it will output 0 THEN increments the pointer." is not correct.
The postfix increment returns the value of the pointer. Consider this value as a copy of the original pointer's value. The pointer is incremented which does not affect the copy.
The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented. ... C11dr 6.5.2.4 2
Then the copy of the pointer is de-referenced and returns the 0. That is the functional sequence of events.
Since the side-effect of incrementing the pointer and de-referencing that copy of the pointer do not effect each other, which one occurs first is irrelevant. The compiler may optimized as it likes.
"the end of the line" is not involved in code. It is the end of the expression that is important.

There is no difference in meaning between *p++ and *(p++).
This is because postfix operators have a higher precedence than unary operators.
Both these expressions mean "p is incremented, and its previous value is dereferenced".
If you want to increment the object being referenced by the pointer, then you need to override precedence by writing (*p)++.
No version of your code can produce output and then increment p. The reason is that p is incremented in an argument expression which produces a value that is passed into printf. In C, a sequence point occurs just before a function is called. So the new value of p must settle in place before printf executes. And the output cannot take place until printf is called.
Now, you have to take the above with a slight grain of salt. Since p is a local variable, modifying it isn't an externally visible effect. If the new value of p isn't used anywhere, the increment can be entirely optimized away. But suppose we had an int * volatile p; at file scope, and used that instead. Then the expression printf("...", *p++) has to increment p before printf is called.

The expression p++ has a result (the value of p before the increment) and a side effect (the value of p is updated to point to the next object of type int).
Postfix ++ has higher precedence than unary *, so *p++ is already parsed as *(p++); you will see no difference in behavior between those two forms. IOW, the dereference operator is applied to the result of p++; the line
printf("%d", *p++);
is roughly equivalent to
printf("%d", *p);
p++;
with the caveat that p will actually be updated before the call to printf1.
However, (*p)++ will be different; instead of incrementing the pointer, you are incrementing the thing p points to.
1. The side effect of a ++ or -- operator must be applied before the next sequence point, which in this particular case occurs between the time the function arguments are evaluated and the function itself is called.

Here is my take on this. Let's ignore the printf function altogether and make things simpler.
If we said
int i;
int p=0;
i = p++;
Then i would be equal to zero because p was equal to zero but now p has been incremented by one; so now i still equals zero and p is equal to 1.
Ignoring the declarations of i and p as integers, if we wrap this as in the example, i = *(p++), then the same action occurs but i now contains the value pointed at by p which had the value of zero. However, the value of p, now, has been incremented by one.

Related

Difference between ++*p++ and *++p++?

What is the difference between ++*p++ and *++p++ (where p is a pointer) in C?
I keep getting an error when I do the second one; can somebody explain, as it's been in my head for days. I checked on Quora and other websites but I couldn't find anything useful.
I want to know why the first one is acceptable but not the latter.
#include <stdio.h>
int main()
{
int arr[]={3,9,0,4,5};
int *ptr=arr;
printf("%d ",*++ptr++);
printf("%d ",*ptr);
return 0;
}
The issue here is a question of operator precedence and the nature of the result of the postfix increment operator (i.e. p++).
In C, that postfix increment operator has the highest priority of all; then, the prefix increment and indirection (*) operator have equal priority, and have right-to-left associativity.
So, adding parentheses to your expressions, to clarify the order of evaluation, we get the following:
*++ptr++ becomes *( ++(p++) )
++*ptr++ becomes ++( *(p++) )
Now remember that the result of the postfix operation is a so-called "rvalue" § – that is, something that can be used on the right-hand side of an assignment but not on the left-hand side. (For example, the constant, 3 is an rvalue: x = 3 is a valid operation but 3 = x is clearly not.)
We can now see that, in your first expression, inside the outer brackets that I have added, we are trying to increment the result of the p++ operation – and that is not allowed. However, in the second case, we are only dereferencing that result (which is a pointer) and then (outside the outer brackets) incrementing the pointed-to variable – which is allowed.
When I compile your code with clang-cl, the error is:
error : expression is not assignable
As (hopefully) explained above, the "expression" referred to is p++.
§ Formally, the result of the postfix increment operator is (a copy of) the value of its operand; that value is not modifiable or assignable.
This is definitely a strange and surprising result. To understand what's going on, it will help to take a closer result at what the "autoincrement" operators ++x and x++ really do.
Most expressions simply compute new values. If I say
a = b * 3;
that means, "take the value of the variable b, multiply it by 3, and that's the value we'll assign to a". Similarly, if I say
a = a + 1;
that means, "take the (old) value of the variable a, add 1 to it, and that's the new value we'll assign back to a".
But ++ is special, because it has the "assign the value back" part built in. Any time you use ++ (or --), two things are happening: we're computing a new value, but we're also modifying the variable whose value we just fetched.
To make this very clear, if I say
a = ++b;
that means, "take the value of the variable b, add 1 to it, assign that new value back to b, and that's the value we'll assign to a". That's for the "prefix" form ++b. For b++, it's a little different:
a = b++;
That means, "take the value of the variable b, add 1 to it, assign that new value back to b, but the value we'll assign to a is the old value of b, before we added 1 to it." In other words, the value of the subexpression b++, the value that "pops out" to participate in the larger expression, is the old value of b.
The other thing to keep in mind here is that when it comes to assigning values, we obviously need a variable to assign the value to. We can't say
3 = b * 3; /* WRONG */
On the right-hand side of the = sign, we fetch b's value and multiply it by 3, but then where we store the new value? On the left-hand side of the = sign, 3 is not the name of a variable, nor is it any kind of a location where we can store a value. So an assignment like this is illegal.
(Formally, what we've been talking about here is the difference between an rvalue and an lvalue. Those are interesting and useful terms that you might want to learn about some day, perhaps even today, but I'm not going to say anything more about them for now.)
But now we have almost enough information to answer your original question. Let's look at the expression that worked:
++*ptr++
What the heck does that mean?
In one sense, it's kind of meaningless, because it's not something that you would probably ever write in a real program. It has very little practical value, which is actually kind of good, which means it's not so bad that, at first glance, it's pretty badly cryptic, in that it's not obvious what it should do.
To understand what it does, we have to be clear about the precedence. Which operands bind more tightly to their operands? Precedence is what tells us that if we write
1 + 2 * 3
the multiplication operator * binds more tightly, meaning that the expression is evaluated as if we had written
1 + (2 * 3)
Now, it happens that the autoincrement operator ++ binds more tightly that the unary contents-of operator *. That is, when we write
++*ptr++
the expression is evaluated as if we had written
++ *(ptr++)
So the first thing we're going to do, inside the parentheses, is ptr++. This means, as we saw before, "take the value of the variable ptr, add 1 to it, assign that new value back to ptr, but the value that pops out to the larger expression is the old value of ptr, before we added 1 to it."
And then the next thing that happens in the "larger expression" is the * or contents-of operator. * works on a pointer, and accesses the object pointed to by the pointer. In your original program, the object pointed to by the pointer ptr was the first cell of the array arr, that is, arr[1]. So * is going to operate on whatever the old value of ptr was, whatever ptr used to point to. And that's arr[0]. So what we end up doing is the equivalent of
++(arr[0])
We're going to take arr[0]'s old value, add 1 to it, store it back in arr[0], and (since this is prefix ++ we're talking about), the value that will "pop out" to the larger expression would be the new value of arr[0]. So, if you had written
printf("%d\n", ++*ptr++);
it would have printed the new value of arr[0], or 4.
The bottom line is that although ++*ptr++ is a complicated-looking expression that's hard to understand and does something so obscure that it might not even be useful, it does do something, and is legal.
So now, finally, it's time to look at
*++ptr++
What does that do?
The first thing we have to know is whether prefix ++ or postfix ++ binds more tightly. It's a question that hardly ever comes up (and we're about to see why), but the answer is that postfix ++ binds more tightly. So this expression is interpreted as if you had written
* ++(ptr++)
So, once again, the first thing we're going to do is take ptr's value, add 1 to it, store that new value back into ptr, and then the value that's going to "pop out" to the larger expression is going to be the old value — but only the old value — of ptr.
Let me say that again. The value that "pops out" to the larger expression is just the old value of ptr. By that time we no longer know or care that it was the variable ptr that we got this value from.
So then we come to the prefix ++. And now we have a serious problem. Remember, ++ wants to fetch a value from an object, add 1 to it, and store the new value back into an object. But at this point we don't have an object to fetch from or store to, we just have a value — remember, the old value of the variable ptr.
This will be easier to understand if we think about integer variables, instead of pointer-to-integer. Suppose I said
int a;
int b = 5;
a = ++(b++);
So we fetch b's value, which is 5, and add 1 to it, and store the new value — which is 6 — back in b, and the value that "pops out" to the larger expression s the old value of b. So now it's as if we had written
a = ++5; /* WRONG */
And this makes no sense. We can't "fetch the old value from the variable 5", because 5 isn't a variable. It's just as wrong as when we said 3 = b * 3;, and for the same reason.
You might also be interested in Question 4.3 in the C FAQ list.

Order of Evaluation in C Operators

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.

Why doesn't this program print '4'? [duplicate]

This question already has answers here:
Post-increment on a dereferenced pointer?
(13 answers)
Closed 3 years ago.
Shouldn't ptrj value be 4 after the execution of *ptrj++?
int j=3,*ptrj = NULL;
ptrj = &j;
*ptrj++;
printf("%i",*ptrj);
*ptrj++ is the same as *(ptrj++). What you expect is instead (*ptrj)++. You should look up operator precedence to learn more about which operators that acts before others. To understand what ptrj++ does, you should read about pointer arithmetic. But here is a quick explanation:
*(ptrj++) returns the value that ptrj points to (3), and THEN increments ptrj to point to the next value.
(*ptrj)++ returns the value that ptrj points to (3), and THEN increments the value that ptrj points at from 3 to 4.
This means that what you're printing is the value at address &j + 1, which is the value that lies right after the variable j in memory. and this is undefined behavior. As Sourav pointed out, you would get a warning that points you to this if you enable compiler warnings.
The only difference between *ptrj++ and ptrj++ is what it is returning. And since you don't use the return value, your code is equivalent to:
int j=3,*ptrj = NULL;
ptrj = &j;
ptrj++;
printf("%i",*ptrj);
If you compile the program with warnings enabled, you'll see
source_file.c:9:5: warning: value computed is not used [-Wunused-value]
*ptrj++;
^
That means, the value computation is useless.
In other words, according to the operator precedence *ptrj++; is same as *(ptrj++);, and as per the post-increment operator property, the value of the operation is the value of the operand, and the value is increased as the side-effect.
Quoting C11, chapter
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). [....]
So, this is same as
*ptr;
ptr++;
If you want to increment that value at the address, you need to enforce the operator precedence by using explicit parenthesis, like
(*ptrj)++; // first get the value, then update the value.
*ptrj++ is equivalent to *(ptrj++).
desired output can be achieved using (*ptrj)++.
Please refer https://www.geeksforgeeks.org/c-operator-precedence-associativity/ to get how operator works.
Precedence of postfix ++ is higher than *. The expression *ptrj++ is treated as *(ptrj++) as the precedence of postfix ++ is higher than *.If you want to print 4 ( ie ptrj+1 ),You should use the following code:-
int j=3,*ptrj = NULL;
ptrj = &j;
(*ptrj)++;
printf("%i",*ptrj);
return 0;
To know more about operator precedence, refer follow link:
https://en.cppreference.com/w/c/language/operator_precedence

Confusing answers : One says *myptr++ increments pointer first,other says *p++ dereferences old pointer value

I would appreciate if you clarify this for me.Here are two recent questions with their accepted answers:
1) What is the difference between *myptr++ and *(myptr++) in C
2) Yet another sequence point query: how does *p++ = getchar() work?
The accepted answer for the first question,concise and easily to understand states that since ++ has higher precedence than *, the increment to the pointer myptr is done first and then it is dereferenced.I even checked that out on the compiler and verified it.
But the accepted answer to the second question posted minutes before has left me confused.
It says in clear terms that in *p++ strictly the old address of p is dereferenced. I have little reason to question the correctness of a top-rated answer of the second question, but frankly I feel it contradicts the first question's answer by user H2CO3.So can anyone explain in plain and simple English what the second question's answer mean and how come *p++ dereferences the old value of p in the second question.Isn't p supposed to be incremented first as ++ has higher precedence?How on earth can the older address be dereferenced in *p++Thanks.
The postfix increment operator does have higher precedence than the dereference operator, but postfix increment on a variable returns the value of that variable prior to incrementing.
*myptr++
Thus the increment operation has higher precedence, but the dereferencing is done on the value returned by the increment, which is the previous value of myptr.
The answer in the first question you've linked to is not wrong, he's answering a different question.
There is no difference between *myptr++ and *(myptr++) because in both cases the increment is done first, and then the previous value of myptr is dereferenced.
The accepted answer for the first question,concise and easily to understand states that since ++ has higher precedence than *,
Right. That is correct.
the increment to the pointer myptr is done first and then it is dereferenced.
It doesn't say that. Precedence determines the grouping of the subexpressions, but not the order of evaluation.
That the precedence of ++ is higher than the precedence of the indirection * says that
*myptr++
is exactly the same (not on the cource code level, of course) as
*(myptr++)
and that means that the indirection is applied to the result of the
myptr++
subexpression, the old value of myptr, whereas (*myptr)++ would apply the increment operator to what myptr points to.
The result of a postfix increment is the old value of the operand, so
*myptr++ = something;
has the same effect as
*myptr = something;
myptr++;
When the side-effect of storing the incremented value of myptr happens is unspecified. It may happen before the indirection is evaluated, or after that, that is up to the compiler.
Section 6.5.2.4 of the C specification discusses the postfix increment and decrement operators. And the second paragraph there pretty much answers your question:
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.
So given *myptr++, yes it's true the the ++ part has higher precedence; but precedence does not exclusively determine your result. The language defines that with the specs. In this case the value of myptr is returned, then the "side effect" of myptr being incremented is executed.

Does *p++ increment after dereferencing? [duplicate]

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).

Resources