2

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.

Jens Erat
  • 35,775
  • 16
  • 76
  • 95
volni
  • 4,836
  • 8
  • 37
  • 44
  • 3
    For future reference "didn't work." is *not* a helpful description of the failure mode. How did the result differ from what you expected? – dmckee --- ex-moderator kitten Feb 01 '10 at 04:45
  • on unrelated note, whenever doing non-obvious stuff, use parenthesis. You may remember now ++ is above * in operator priority table, but after 7 hours of coding straight you really, really begin to wonder whether *s++; means *(s++); or (*s)++; – SF. Feb 01 '10 at 08:18
  • just as a side note: take another name for that function. This is not how strncat works. – quinmars Feb 01 '10 at 12:34

5 Answers5

15

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
  • 213,251
  • 44
  • 377
  • 423
6

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
  • 32,385
  • 4
  • 57
  • 92
4

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

hpsMouse
  • 1,984
  • 14
  • 19
2

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.

rjh
  • 47,556
  • 3
  • 51
  • 61
Mahmoud Al-Qudsi
  • 27,112
  • 12
  • 82
  • 123
0

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
  • 33,335
  • 12
  • 80
  • 87
  • 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. Feb 01 '10 at 14:31
  • 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 Feb 01 '10 at 14:36