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
  • 37,523
  • 16
  • 80
  • 96
volni
  • 5,196
  • 8
  • 38
  • 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.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
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
  • 33,512
  • 4
  • 61
  • 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
  • 2,004
  • 15
  • 20
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
  • 49,276
  • 4
  • 56
  • 63
Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125
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
  • 35,221
  • 12
  • 85
  • 90
  • 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