Question

I'm sure this has been asked many times before but this kind of thing is pretty difficult to search for.
Say foo and bar are both pointers to separate arrays, what does this line do?

*foo++ = *bar++;

At what point does each pointer get incremented, and is it an assignment of pointers or values?
Thank you

Was it helpful?

Solution

*foo++ = *bar++;

copies what bar points at over what foo points at. Then it increments both pointers to the next element.

OTHER TIPS

the postfix ++ operator will increment the pointer, but the result of the expression foo++ is the address stored in the pointer before the increment. What is dereferenced is the value of foo and bar before being incremented. The assignment then happens on those types. It's roughly equivalent to

*foo = *bar;
++foo;
++bar;

If you're unfamiliar, incrementing a pointer causes it to point to the next element in a sequence. The following two loops accomplish the same task

for (int i = 0; i < 10; ++i) {
    p[i] = 0;
}

for (int i = 0; i <10; ++i, ++p) { // NOTE the extra ++p
    *p = 0;
}

generally you increment a pointer as long as the value being pointed to is not equal to some "end" value. With char* this is usually the '\0' character. the example you posted is seen often in a while loop using two char* types. while(*foo++ = *bar++). This loop will continue until the value assigned to *foo is of 0 value, which the \0 character is.

Since post-increment has higher precedence than (binds more tightly than) the unary * operator, this:

*foo++ = *bar++;

is equivalent to:

*(foo++) = *(bar++);

The expression foo++ yields the unmodified value of foo; likewise, bar++ yields the unmodified value of bar. (That's not all it does; we'll get to the rest in a moment.) So the assignment copies the value of the object that bar points to into the object that foo points to. So far, it's equivalent to:

*foo = *bar;

which I presume doesn't need further explanation.

The value of the expression foo++ is simply the value of foo, but as a side effect it also causes the value of foo to be incremented. foo = foo + 1 has the same side effect (though it yields a different value). So evaluating

*foo++ = *bar++;

will at some point cause both foo and bar to be incremented. For this to make sense, both foo and bar need to point to elements of an array, and each will be advanced to point to the next element of the array.

The time at which these side effects occur is not specified. The values of foo and bar could be updated in either order, before or after *foo is updated. As long as foo and bar are distinct pointers, this doesn't matter, since the three side effects can't interfere with each other.

Finally, the assignment is itself an expression, and the value it yields is the value that was stored in *foo. In this case, that value is discarded.

Breaking it down, and assuming foo and bar are of type some_type*, *foo++ = *bar++; could be written as:

some_type *foo_tmp = foo;
some_type *bar_tmp = bar;
*foo_tmp = *bar_tmp;
foo = foo + 1;
bar = bar + 1;

with the three assignments being executed in some unspecified order (any of the 6 possible orders is allowed). If the order matters, the behavior is undefined. This expansion ignores the value yielded by the assignment.

This kind of expression can be used to implement the strcpy() function:

char *strcpy(char *dest, const char *src) {
    while (*dest++ = *src++)
        ;
}

All the copying is done by the assignment expression that's used as the condition in the while loop, and the test for completion of the loop is based on the value that the assignment yields, i.e., the char value that was copied. The loop terminates when the value copied is a null character, '\0', which is treated as a false condition. It's a bit too terse for some people's tastes, mine included, but it's a common idiom.

Take a simple example:

char s1[] = "I am bar";
char s2[10];

char* bar = s1;  // bar points to the first element of s1
char* foo = s2;  // foo points to the first element of s2

*foo++ = *bar++; // Copies 'I' to s2[0]
                 // Now bar points to the second element of s1
                 // foo points to the second element of s2

*foo++ = *bar++; // Copies ' ' to s2[1]
                 // Now bar points to the third element of s1
                 // foo points to the third element of s2

post-increment operator ++ has higher precedence than the indirection operator *. Therefore, the following statements are equivalent

*foo++ = *bar++;
// equivalent to
*(foo++) = *(bar++);

At what point does each pointer get incremented, and is it an assignment of pointers or values?

foo++ evaluates to foo. Its side-effect is to increment the pointer foo to make it point to the next element.

Similarly bar++ evaluates to bar and its side-effect is to make bar point to the next element. Therefore, this statement assigns the object pointed to by bar to the object pointed to by foo. The side-effects take place before the next sequence point. In this case, it is the end of the statement marked by the semi-colon. Therefore, the pointers foo and bar are incremented after the assignment statement is executed.

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