Just had a chat with a C guy today and we disagreed on the following:
int intgA[2] = { 1, 2 };
int intgB[2] = { 3, 5 };
int *intAPtr = intg
You and the other guy both are wrong!
Either,
1. both pointers increment first and then assignment takes place or
2. one pointer increments, then the assignment happens, then the other pointer increments or
3. first assignment takes place and then pointers increments.
But the rule is that, all the side effects of one statement have to be complete before the next statement starts. Keep in mind that the original values must be used. As long as the original value is used, the increment can happen at any time.
C-faq: 3.2:
It is not guaranteed that an increment or decrement is performed immediately after giving up the previous value and before any other part of the expression is evaluated. It is merely guaranteed that the update will be performed sometime before the expression is considered "finished".
Read this answer given by Eric Lippert for detailed explanation.
The statement
*intAPtr++ = *intBPtr++;
is parsed as
*(intAPtr++) = *(intBPtr++);
and breaks down as follows:
intBPtr
(3) is assigned to the location pointed to by intAPtr
(intgA[0]
); intAPtr
and intBPtr
are incremented.The exact order in which these things happen is unspecified; you cannot rely on intBPtr
being incremented after intAPtr
or vice-versa, nor can you rely on the assignment occuring before the increments, etc.
So by the time this is all done, intgA[0] == 3
and intAPtr == &intgA[1]
and intBPtr == &intgB[1]
.
The expression a++
evaluates to the value of a
before the increment.
I agree with John Bode answer to simplify it a bit I will just write it in code:
*intAptr = * intBPtr;
is equal to:
*intAptr =*intBPtr
intAPtr+=1;
inrBPtr+=1;
so what we get is:
intAPtr
points to 2
intBPtr
points to 5
Yes, ++
binds tighter than *
, but you have misunderstood how it works. var++
increments var
, but it evaluates to the value of var
before the increment. You can think of it as syntactic sugar for (var += 1, var - 1)
if you like.
Another way to think about this is: if it worked the way you thought it did, then there would be no difference between var++
and ++var
, and one of them would not have been included in the language in the first place. C has almost no redundancies.
(The binding precedence does matter; for instance, it means *var++
increments the value of the variable var
whereas (*var)++
increments the value in the memory location at *var
.)
Example code (In linux):
#include <stdio.h>
#include <stdlib.h>
int main() {
int intgA[2] = { 1, 2 };
int intgB[2] = { 3, 5 };
int *intAPtr = intgA; //1
int *intBPtr = intgB; //3
*intAPtr++ = *intBPtr++;
// *intAPtr = *intBPtr;
// *intAPtr++ = 25;
printf("op: %d %d\n", *intAPtr, *intBPtr);
return 0;
}
output:
op: 2 5
first its assigning intBPtr
to intAPtr
then increment take place, Because it is post increment.
The main effect of the ++
operator is to produce the value of its operand (without having incremented it). The side effect is to increment the operand.
Even if the side effect is performed before the value produced by the main effect is used in another operation, the value produced by the main effect is the original value of the operand, not the updated value.
In *x++
, which is parsed as *(x++)
, the *
operator is applied to the value produced by the main effect, so the *
operation is the same as if *x
is evaluated. The increment happens “on the side”, outside of the main expression evaluation, so it takes no part in determining the value of *x++
.