tags:

views:

295

answers:

4

I'm looking at a strcpy example where they increase the value of a pointer, and assign it in 1 line, like this:

*ptrA++ = *ptrB++;

I know that the value where the pointer is pointing to in the char array is increased, and the contents is copied.

does c do something like

*ptrA = *ptrB;
ptrA++;
ptrB++;

in the background ?

+1  A: 

You got it. (15 char)

int3
+7  A: 

Yes it does, remember that the postfix ++ means return the value before the increment. So *ptrA++ increments ptrA but returns the dereference of of ptrA before the increment.

Ramónster
+2  A: 

Yes, it does. Because the code is using postfix operators:

Postfix operators are operators that are suffixed to an expression.

operand++;

This causes the value of the operand to be returned. After the result is obtained, the value of the operand is incremented by 1.

Gerd Klima
+6  A: 

Well, yes and no.

Yes, because the second piece of code you provided does indeed do the same thing as the original code. So, in a way, you understood your original code correctly.

No, because your second piece code is not really equivalent to the original one. Remember, it is incorrect to say that postfix ++ operator returns the original value first and increments the pointer later. In C language temporal relationships (what happens "before" and what happens "after") can only be defined by sequence points. The expression

*ptrA++ = *ptrB++;

has no sequence points inside, so there's absolutely no way to say what happens before and what happens after. At the same time, your second variant

*ptrA = *ptrB;
ptrA++;
ptrB++;

explicitly guarantees that increment happens after the dereference, since there's a sequence point at the end of each statement. There's no such guarantee with regard to the first variant. This is what I see as a problem with your interpretation.

In reality it is quite possible that the increment will happen first and the dereference will happen later. For example, the compiler can translate your original expression into something like

tmp1 = ptrA++;
tmp2 = ptrB++;
*tmp1 = *tmp2;

in which case the increment happens first. Or the compiler can translate it into something like

ptrA++;
ptrB++;
*(ptrA - 1) = *(ptrB - 1);

in which case the increment happens first as well.

Once again, remember your interpretation of the original expression is good, but it is just one of the possible interpretations. Never assume that things will happen in the specific order you used in your interpretation.

P.S. About those sequence points: C FAQ, C++ FAQ, Wikipedia

AndreyT
IMHO a compiler can probably do instruction reordering in both cases. But yes, the OP's original method might make it more obvious for a less aggressively optimizing compiler.
int3
This is a neat writeup. Can you point us to the definition of a sequence point?
Andres Jaan Tack
@ Andres: See the P.S. part of the answer
AndreyT
Nitpicking about the snippet with tmp1 and tmp2: saying the increment happens first threw me for a moment. The assignment to tmp1 and tmp2 is still happening before the incrementation of ptrA and ptrB, but I acknowledge that's obvious but it may temporarily confuse new C coders.
James Morris
So in the real world I cannot assume my original code works as I think it does, and I should instead go for assinging first, then increment the pointers ?
zlack
@zlack: No, your code is perfectly fine, it does what you want it to do and it does it correctly. Just don't assume that you can always interpret the postfix `++` as "return the old value first, increment later". For example, if you did `*ptrA++ = *ptrA++;` (note, on both sides it is the same pointer), your interpretation would not apply, since this specific expression produces undefined behavior.
AndreyT