Question

Background

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 = intgA;
int *intBPtr = intgB;

So when we do:

*intAPtr++ = *intBPtr++;

My analysis

First:

intBPtr increments by one, now pointing to the address of 5. Then, deference, holding the value 5;

intAPtr also increments by one, now pointing to the address of 2. Subsequently referencing and the value is 2;

Lastly:

2 is replaced by 5.

So respectively they are: 5 and 5.

His analysis

The value of *intBPtr is first assigned to *intAPtr first.

Hence, they become: 3 and 3.

Then both *intAPtr and *intBPtr is incremented by one.

So, respectively they become: 4 and 4.

My Assumption

I thought the ++ operator takes precedence both over * and =, hence my assertion.

For example if we had:

*intAPtr++; 

The result should be 2, right? Because we first increment the pointer and then dereference.

So why in the above case, as he claims, we first assign the value of intBPtr to the value of intAPtr and increment the values last?

After having taken all suggestions here, I ran the code in IDE and the result confirms that of @sujin:

Although it confirms that I was right at least in terms of precedence:

That: *intAPtr++ = *intBPtr++;

intAPtr++ has a higher precedence, which leads to: intAPtr increments its address by 1.

Now pointing to: the address of 2.

And likewise:

intBPtr++ also increments by 1 (address).

Now pointing to: the address of 5.

Then it's *'s turn:

So the both get dereferenced (*) to respectively 2 and 5.

But the problem exists still because the assignment above (=) did not seem to take place.

If it did both would become 5.

Looking forward to being further enlightened.

Was it helpful?

Solution

The statement

*intAPtr++ = *intBPtr++;

is parsed as

*(intAPtr++) = *(intBPtr++);

and breaks down as follows:

  • The value currently pointed to by intBPtr (3) is assigned to the location pointed to by intAPtr (intgA[0]);
  • The pointers 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.

OTHER TIPS

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.

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

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

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top