Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C pointers: difference between while(*s++) { ;} and while(*s) { s++;}

Tags:

c

pointers

I'm going through K & R, and am having difficulty with incrementing pointers. Exercise 5.3 (p. 107) asks you to write a strcat function using pointers.

In pseudocode, the function does the following:

  1. Takes 2 strings as inputs.
  2. Finds the end of string one.
  3. Copies string two onto the end of string one.

I got a working answer:

void strcats(char *s, char *t)
{
    while (*s)            /* finds end of s*/
        s++;
    while ((*s++ = *t++)) /* copies t to end of s*/
        ;
}

But I don't understand why this code doesn't also work:

void strcats(char *s, char *t)
{
    while (*s++)
        ;
    while ((*s++ = *t++))
        ;
}

Clearly, I'm missing something about how pointer incrementation works. I thought the two forms of incrementing s were equivalent. But the second code only prints out string s.

I tried a dummy variable, i, to check whether the function went through both loops. It did. I read over the sections 5.4 and 5.5 of K & R, but I couldn't find anything that sheds light on this.

Can anyone help me figure out why the second version of my function isn't doing what I would like it to? Thanks!

edit: Thanks everyone. It's incredible how long you can stare at a relatively simple error without noticing it. Sometimes there's no better remedy than having someone else glance at it.

like image 507
Graeme Avatar asked Dec 04 '22 17:12

Graeme


2 Answers

This:

while(*s++)
    ;

due to post-increment, locates the nul byte at the end of the string, then increments it once more before exiting the loop. t is copied after then nul:

scontents␀tcontents␀

Printing s will stop at the first nul.

This:

while(*s)
    s++;

breaks from the loop when the 0 is found, so you are left pointing at the nul byte. t is copied over the nul:

scontentstcontents␀
like image 152
Mark Tolonen Avatar answered Dec 07 '22 22:12

Mark Tolonen


It's an off-by-one issue. Your second version increments the pointer every time the test is evaluated. The original increments one fewer time -- the last time when the test evaluates to 0, the increment isn't done. Therefore in the second version, the new string is appended after the original terminating \0, while in the first version, the first character of the new string overwrites that \0.

like image 43
Ernest Friedman-Hill Avatar answered Dec 07 '22 22:12

Ernest Friedman-Hill