Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

pointers in while loop 3

Status
Not open for further replies.

rsshetty

Programmer
Dec 16, 2003
236
US
main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%sn”,p2);

}

I stumbled upon this piece of code when I was reading about C programming. The output of this code is an empty string. I don't understand what is happening in the while loop. I am completely stumped.
Any insight would be very helpful.

rsshetty.
It's always in the details.
 
Code:
while (*p2++ = *p1++)
    ;

First, whoever wrote the code apparently made a mistake. We'll fix it in a bit.

Also, you've probably already noticed that all the action takes place in the condition of the while loop; the body is just a blank statement.


Now, forget the [tt]++[/tt] operators for a second. In fact, ignore the while loop right now. Pretend it just says:
Code:
*p2 = *p1

That statement should be understandable as long as you know pointer syntax: the character [tt]p2[/tt] is pointing to gets assigned the value of the character that [tt]p1[/tt] is pointing to.


Okay, now put the while loop back in (leave the [tt]++[/tt]s out), and add a body:
Code:
while (*p2 = *p1)
{
    p2++;
    p1++;
}

Since we've already decided that the while loop "condition" copies a character at [tt]p1[/tt] to [tt]p2[/tt], and since the body of the loop moves each of [tt]p1[/tt] and [tt]p2[/tt] to the following character, the effect of the entire while loop is to copy the string initially pointed at by [tt]p1[/tt] into the blank memory at [tt]p2[/tt].

Read that again and make sure you understand what's going on.

You may have two questions, now: what "condition" keeps the loop going, and what "condition" stops it?

To answer the first question, note that any non-zero value results in "true" for the while loop's purposes. Also note that an assignment expression evaluates to the value that was assigned. Thus, the while loop continues as long as non-zero values (non-null characters) are copied over.

That should make the answer the the second question fairly obvious: the loop stops as soon as zero gets assigned. And zero gets assigned when you hit the null character (zero value character at the end of every string) at the end of [tt]p1[/tt] and copy it over to [tt]p2[/tt].


Now, our code is almost the same as the version you posted. The only difference is that we increment the pointers in the body of the while loop, while the initial code increments it in the condition.

Note that there are two ways to use the [tt]++[/tt] operator:
Code:
++i;  /* preincrement */
and
Code:
i++;  /* postincrement */

The first form, preincrement, increments the variable and evaluates to the new value.

The second for, postincrement, increments the variable and evaluates to the old value.

Since the initial code uses postincrement, it increments each pointer, but copies to and from their old locations. That property allows you to compact an increment into a statment that's actually doing something.

So the condition is just a short way of saying, "Copy over one character, and leave the pointers pointing at the next character position," and the effect of the whole while loop is just to copy the string from one place to another.


Phew. Finally, you may now be wordering about that mistake I mentioned, and about why, if the string really got copied, it never prints out.

Well, [tt]p2[/tt] does initially point to where the new string will start. However, as the characters get copied, [tt]p2[/tt] moves along, always staying at the end of the string. At the time of the call to [tt]printf[/tt], [tt]p2[/tt] is sitting right on a null character, which explains the empty string output when [tt]p2[/tt] is printed.

To remedy this and print the copied string, just create another pointer, set it to the start of the string (the same place [tt]p2[/tt] starts), and leave it there.

e.g.
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

main()
{
        char *p1=“name”;
        char *p2;
        char *copied_string;

        p2 = malloc(20);
        copied_string = p2;

        memset (p2, 0, 20);

        while(*p2++ = *p1++)
             ;

        printf(“%s\n”,copied_string);

}


(By the way, that cast on the return value of malloc can be dangerous; I removed it in favor of including the proper header).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top