1

It's about strcat function.

while (*p)
    p++;

and

while (*++p)
    ;

both works, but

while (*p++)
    ;

does not work. I think first and third should be same, but it's not.

Guixing Bai
  • 350
  • 2
  • 11
  • 3
    2 and 3 would only be equal if pre and post increment were the same operator – David Heffernan Aug 30 '12 at 16:56
  • `while (*p++)` does not make `strcat` function works. – Guixing Bai Aug 30 '12 at 16:57
  • What is "works" and "does not work" supposed to mean in this case? I can write a `strcat` function using any of the three and all of them will "work" perfectly. – AnT stands with Russia Aug 30 '12 at 17:05
  • @AndreyT: I'm going to take a massive leap and assume that this is the first line of our proposed `strcat` implementation, and that the next line is a call to `strcpy` with `p` as the destination. – Steve Jessop Aug 30 '12 at 17:11
  • Correction, not the first line, because `strcpy` returns the original destination. So there needs to be another pointer equal to `p` before we start moving `p`. – Steve Jessop Aug 30 '12 at 17:24
  • @Steve Jessop: Precisely. But since we are writing `strcat`, I don't think we should use `strcpy` either, meaning that the actual copying should also be spelled out explicitly. Maybe we should outsource... – AnT stands with Russia Aug 30 '12 at 17:25
  • Anyway, I think the question is about why these code snippets are different, not about how to implement `strcat`. The usefulness of one or more of the snippets in implementing `strcat` is interesting but (I think) irrelevant. And I think we can probably call `strcpy` from `strcat` whether we have to implement it ourselves or not, provided that we implement `strcpy` *first* :-) – Steve Jessop Aug 30 '12 at 17:26

4 Answers4

7

Let's assume that p is a string.

while (*p) p++; /* (1) */
while (*++p) ;  /* (2) */
while (*p++) ;  /* (3) */
  • (1) is different from (2) if p is an empty string.
  • (1) is different from (3) because with (3), even if the current value of *p is a '\0' character, p is incremented.
md5
  • 23,373
  • 3
  • 44
  • 93
4

Both

while (*p) p++;

and

while (*++p) ;

will advance p to point to the 0 terminator in a string, whereas

while (*p++) ;

will advance p to point one character past the 0 terminator.

To see why, let's assume the following characters in memory:

Address         0x00 0x01 0x02 0x03
-------         ---- ---- ---- ----
0x8000           'a'  'b'  'c'   0
0x8004           ...

Assume that p starts at address 0x8000. Here's how the first loop plays out:

1.  *p = 'a'
2.  p = 0x8001
3.  *p = 'b'
4.  p = 0x8002
5.  *p = 'c'
6.  p = 0x8003
7.  *p = 0
8.  end loop

Here's how the second loop plays out:

1.  p = 0x8001
2.  *p = 'b'
3.  p = 0x8002
4.  *p = 'c'
5.  p = 0x8003
6.  *p = 0
7.  end loop

And here's the last one:

1.  *p = 'a'
2.  p = 0x8001
3.  *p = 'b'
4.  p = 0x8002
5.  *p = 'c'
6.  p = 0x8003
7.  *p = 0;
8.  p = 0x8004
9.  end loop

In the last version, evaluating *p++ advances the pointer even if the value of *p is 0.

John Bode
  • 119,563
  • 19
  • 122
  • 198
2
// move p forward as long as it points to a non-0 character,
// leave it pointing to a 0 character.
while (*p) p++;  

// move p forward until it points to a 0 character, skipping the first 
// character before you start
while (*++p);

// move p forward until it points one past a 0 character
while (*p++);

So given that (1) "works": (2) also works if p initially points to a non-empty string. (3) doesn't work at all because p ends up pointing to a different place.

*++p increments p and then evaluates to whatever p now points to. *p++ evaluates to whatever p initially points to, but also increments p. Hence (2) and (3) are different.

(1) and (3) are different because (3) executes the p++, then it decides whether to stop. (1) first looks at *p to decide whether to stop, and if not stopping it executes the p++.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
0

*++p means increment this variable, then use it
*p++ means use the variable, then increment it

MStodd
  • 4,716
  • 3
  • 30
  • 50