Jack O'Connor
Jack O'Connor

Reputation: 195

Why isn't this pointing to the null character in array? ('\0')

Sorry about the poorly worded question, I couldn't think of a better name.

I am learning C, have just moved onto pointers and have written a function, strcat(char *s, char *t), which adds t to the end of s:

void strcat(char *s, char *t) //add t to the end of s
{
    while(*s++)                //get to the end of s
        ;
    *s--;                      //unsure why I need this
    while(*s++ = *t++)         //copy t to the end of s
        ;
    return;
}

Now the question I have is why do I need the line:

*s--;

When I originally added it I thought it made sense until I went through the code.

I would have thought the following was true though:

1) The first loop increments continually and when *s is 0 (or the null character) it moves on so now *s points to the null character of the array.

2) So all I should have to do is implement the second loop. The original null character of s will be replaced by the first character of t until we get to t's null character at which point we exit the second loop and returns.

Clearly I am missing something as the code doesn't work without it!!

After the first loop *s points to one position beyond '\0' but my question is why?

Thanks in advance :)

Upvotes: 1

Views: 159

Answers (4)

TimDave
TimDave

Reputation: 652

You incremented the pointer after checking the value of the location it was pointing at. Functionally this is happening in while( *s++ ):

while( *s )
++s;

Upvotes: 2

alk
alk

Reputation: 70981

First *s is evaluated then s is incremented.

So when reaching s's 0-terminator the loop ends, but s still is incremented one more time.


Also there is no need to do:

  *s--;

Doing

  --s;

or

  s--;

would be enough. There is no need to de-reference s here.

Or simply do

while (*s)
  ++s;

to get rid of --s;'s need at all.

Upvotes: 6

fbafelipe
fbafelipe

Reputation: 4952

Change your first while to:

if (*s) {
    while(*(++s))                //get to the end of s
            ;
}

In your code, you would always be checking if it was pointing to '\0' and then incrementing, so when you reach the '\0' you would check it only on the next iteration, and then you would increment it. Note that changing to pre-increment will not check if the pointer currently points to '\0', so you need to check it before the while.

Note that your code (post-increment and a decrement after the while) might be faster on most platforms (usually a branch is slower than a decrement), my code in this answer is just for you understand the problem.

Upvotes: 1

Guntram Blohm
Guntram Blohm

Reputation: 9819

The ++ operator after the variable name does postincrement, which means it increments by one, but the result of the operator is the value before the increment. If you used ++s, it would be different.

If s is 4 , then s will be 5 after x=++s as well as after x=s++. But the result (value of x) in the first case is 5, while it's 4 in the second case.

So in your while *s++, when s points to the '\0', you increment it, then take the old, un-incremented pointer, dereference it, see the \0, and stop the loop.

Btw, your '*s--' should be s-- because you don't need the character 'behind' the pointer there.

Upvotes: 0

Related Questions