6

The following code confused me a bit:

char * strcpy(char * p, const char * q) {
  while (*p++=*q++);
  //return
}

This is a stripped down implementation of strcpy function. From this code, we see that pointer p and q are incremented then dereferenced and q is assigned to p until the \0 char has been reached.

I would like someone to explain the first iteration of the while loop.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
Davita
  • 8,928
  • 14
  • 67
  • 119
  • 6
    Your definitions of post/pre seem to be backwards. Post = after, Pre = before. The post-increment here shows that the first character will be copied, then the pointer will be incremented. – Marlon Aug 30 '11 at 20:15
  • Why the C++ tag (and title) ? This is a C library function. – Paul R Aug 30 '11 at 20:26
  • 1
    Looks like perfectly valid C++ code to me, @Paul. So why *not* the C++ tag? – Rob Kennedy Aug 30 '11 at 20:29
  • possible duplicate of [How does the pointer assignment in strcpy work?](http://stackoverflow.com/questions/1780093/how-does-the-pointer-assignment-in-strcpy-work) – Rob Kennedy Aug 30 '11 at 20:31
  • @Rob: well it's perfectly valid **Objective-C** code too - perhaps it should be tagged as `Objective-C` then ? – Paul R Aug 30 '11 at 20:33
  • @Davita: not quite - it still says "C++" in the title. – Paul R Aug 30 '11 at 20:36

8 Answers8

9

Because the ++ is after the variables, they aren't incremented until after the expression is evaluated. That's why it's the post-increment operator; the pre-increment is prefixed (++p). *++p would write to the second spot, *p++ writes to the first.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
Kevin
  • 53,822
  • 15
  • 101
  • 132
2

p++ is post-incrementing the pointer p. So the current value of p is operated upon by the deference operator * before p is incremented.

Your reasoning would've been correct if the while loop was written as follows:

while (*++p=*++q);

In this case the increment would happen before dereferencing.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
2

No, the increment happens after the assignment.

If it were *(++p), the pointer p would be incremented and after that assigned.

Alexey Ivanov
  • 11,541
  • 4
  • 39
  • 68
2

The expressions x++ and ++x have both a result (value) and a side effect.

The result of the expression x++ is the current value of x. The side effect is that the contents of x are incremented by 1.

The result of the expression ++x is the current value of x plus 1. The side effect is the same as above.

Note that the side effect doesn't have to be applied immediately after the expression is evaluated; it only has to be applied before the next sequence point. For example, given the code

x = 1;
y = 2;
z = ++x + y++;

there's no guarantee that the contents of x will be modified before the expression y++ is evaluated, or even before the result of ++x + y++ is assigned to z (neither the = nor + operators introduce a sequence point). The expression ++x evaluates to 2, but it's possible that the variable x may not contain the value 2 until after z has been assigned.

It's important to remember that the behavior of expressions like x++ + x++ is explicitly undefined by the language standard; there's no (good) way to predict what the result of the expression will be, or what value x will contain after it's been evaluated.

Postfix operators have a higher precedence than unary operators, so expressions like *p++ are parsed as *(p++) (i.e., you're applying the * operator to the result of the expression p++). Again, the result of the expression p++ is the current value of p, so while (*p++=*q++); doesn't skip the first element.

Note that the operand to the autoincrement/decrement operators must be an lvalue (essentially, an expression that refers to a memory location such that the memory can be read or modified). The result of the expression x++ or ++x is not an lvalue, so you can't write things like ++x++ or (x++)++ or ++(++x). You could write something like ++(*p++) (p++ is not an lvalue, but *p++ is), although that would probably get you slapped by anyone reading your code.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

The right hand side of the expression (*q++) will be evaluated prior to *p++, and both will only be incremented after the assignment takes place.

Read the statement right to left and remember post-increment (q++ instead of ++q) happens after everything else in the line is resolved.

*q --> dereference q
=  --> assign the value
*p --> to p

increment both.

Do this until q p taking q's element = 0 which is when it reaches the null terminator.

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
1

This is a stripped implementation of strcpy function. From this code, we see that pointer p and q are increamented, than dereferenced and q is assigned to p until \0 char has been reached.

It happens the other way around. The value at *p is set to *q, then both pointers are incremented.

When you have int foo = bar++ the increment happens after foo has been set. To have it happen first you would do int foo = ++bar

Alex
  • 14,973
  • 13
  • 59
  • 94
  • 1
    @Marlon, why did you edit my post? you've inverted the meaning, which is incorrect. *p is set to *q, not the other way around unless I'm having a complete brain fart and missing something. – Alex Aug 30 '11 at 20:32
1

The value of q++ is q
The value of ++q is q+1

log0
  • 10,489
  • 4
  • 28
  • 62
1

The while loop's condition is performing post-increment. Equivalently:

while (true) {
    char* old_p = p;
    const char* old_q = q;

    ++p; // or p++;
    ++q; // or q++;

    *old_p = *old_q;
    if (*old_p == '\0')
        break;
}
Dawson
  • 2,673
  • 1
  • 16
  • 18
  • Not quite true, because your while (*p) is looking at the next character, not the one just copied. – Neil Aug 30 '11 at 20:29