views:

202

answers:

5

I'm writing a simple string concatenation program.

The program works the way I have posted it. However, I first wrote it using the following code to find the end of the string:

while (*s++)
    ;

However, that method didn't work. The strings I passed to it weren't copied correctly. Specifically, I tried to copy "abc" to a char[] variable that held "\0".

From reading the C K&R book, it looks like it should work. That compact form should take the following steps.

  1. *s is compared with '\0'
  2. s points to the next address

So why doesn't it work? I am compiling with gcc on Debian.

I found that this version does work:

strncat(char *s, const char *t, int n)
{
    char *s_start = s;

    while (*s)
        s++;

    for ( ; n > 0 && *t; n--, s++, t++)
        *s = *t;

    *(s++) = '\0';

    return s_start;
}

Thanks in advance.

+11  A: 

After the end of while (*s++);, s points to the character after the null terminator. Take that into account in the code that follows.

Chris Jester-Young
+4  A: 

There is difference. In the first case, s will point to the position after '\0', while the second stops right at '\0'.

hpsMouse
+5  A: 

The problem is that

 while (*s++)
     ;

Always Increments s, even when s is zero (*s is false)

 while (*s)
    s++;

only increments s when *s is nonzero

so the first one will leave s pointing to first character after the first \0, while the second one will leave s pointing to the first \0.

John Knoeller
+1  A: 

In addition what has been said, note that in C it is technically illegal for a pointer to point to unallocated memory, even if you don't dereference it. So be sure to fix your program, even if it appears to work.

Peter Eisentraut
the first location after an array is specifically allowed to be pointed to (to allow comparisons with pointers in the array) so this isn't a problem
jk
Addressing one item past the end of an array is a special case that the standard explicitly defines. Here's a topic that contains a discussion about it: http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-the
indiv
@jk: Good point.
Peter Eisentraut
+1  A: 

As John Knoeller said, at the end of the run it'll s will point to the location after the NULL. BUT There is no need to sacrifice performance for the correct solution.. Take a look for yourself:

while (*s++) --s;

Should do the trick.

Computer Guru
Don't you mean to say `while (*s++); --s;`?
Chris Jester-Young
Whoops! Thanks for catching that.. I was on my way out of the door to work when I posted that in a hurry :)
Computer Guru