Reputation: 229
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
Upvotes: 2
Views: 703
Reputation: 9680
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.
Upvotes: 0
Reputation: 263487
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.
Upvotes: 2
Reputation: 36872
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.
Upvotes: 2
Reputation: 206667
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
Upvotes: 1
Reputation: 57784
*foo++ = *bar++;
copies what bar
points at over what foo
points at. Then it increments both pointers to the next element.
Upvotes: 5