1

I was going through the implementation! of strcat function in C. I am unable to understand how they have used the recursion along with pointers.

Below is the code Snippet from that source.

char dest[100] = "I love";
char *src = "food";`

/* my_strcat(dest, src) copies data of src to dest. */
void my_strcat(char *dest, char *src)
{
  (*dest)? my_strcat(++dest, src): (*dest++ = *src++)? my_strcat(dest, src): 0 ;
}
8
  • What bit didn't you understand Commented Jul 12, 2016 at 1:14
  • consider posting to codegolf which deals with curiosities rather than practicalities Commented Jul 12, 2016 at 1:15
  • 1
    because they wanted to do it that way for fun Commented Jul 12, 2016 at 1:19
  • 2
    see the title of the page you linked, "Write one line functions for strcat()" . the point of this page is to do things in an unusual way for fun Commented Jul 12, 2016 at 1:22
  • 1
    @MAP Although the function itself may not be perfect, the snippet as a whole is correct. Which is to say that dest[100] will be filled with all NULs after the string. Commented Jul 12, 2016 at 1:27

2 Answers 2

4

Breaking it into pieces:

(*dest) /* Is *dest different than '\0' ? */
   ? my_strcat(++dest, src) /* *dest is different than '\0', so increment dest pointer so it'll point to the next character and call my_strcat() again. Here we're searching for the end of the string dest. */

   : (*dest++ = *src++) /* *dest is equal to '\0', so we're at the end of *dest... We start to assign *src to *dest and increment both pointers to point to the next character. The lvalue of this assignment is also a comparison (is it different than '\0' ?). */

     ? my_strcat(dest, src) /* The previous comparison is different than '\0', so we'll call my_strcat() again (pointers have already been incremented and they now point to the next character) */

     : 0; /* The previous comparison is '\0', so we've reached the end of the src, so we're done. */

Replacing ternary operators with if/else:

/* Is *dest different than '\0' ? */
if (*dest != '\0') {
  /* *dest is different than '\0', so increment dest pointer so it'll point to the next character and call my_strcat() again. Here we're searching for the end of the string dest. */
  my_strcat(++dest, src);
} else {
  /* *dest is equal to '\0', so we're at the end of *dest... We start to assign *src to *dest and increment both pointers to point to the next character. The lvalue of this assignment is also a comparison (is it different than '\0' ?). */
  if ((*dest = *src) != '\0') {
    /* The previous comparison is different than '\0', so we'll call my_strcat() again (pointers have already been incremented and they now point to the next character) */
    my_strcat(++ dest, ++ src); /* Moved increments down for readability */
  } else {
     /* The previous comparison is '\0', so we've reached the end of the src, so we're done. */
    return; 
  }
}

If/else without comments (maybe it's more readable):

if (*dest != '\0') {
  my_strcat(++dest, src);
} else {
  if ((*dest = *src) != '\0') {
    my_strcat(++ dest, ++ src);
  } else {
    return; 
  }
}
Sign up to request clarification or add additional context in comments.

Comments

2

This is a pretty poor implementation, but I guess it does work. The first ?: tests if the destination string is at end. If not it bumps the destination pointer and then calls itself recursively. If the destination is already at the end, it then copies one character, bumping both pointers and tests for zero. If that wasn't the trailing NUL from src, it then calls itself recursively with the updated pointers.

Oh, wait, there's a bug (or maybe a "feature"). It assumes that all of the characters after the end of dest are initially filled with NULs. I guess you could actually leverage that, if you can rely on the implemention continuing to have this property and have a dest string with text interspersed with NUL characters and it would fill in those NULs out of src, one character at a time.

And that's not to mention the excessive use of recursion which means that you will have as many call frames on the stack as there are characters in the resulting string. Where did you get this silly strcat implementation from? Certainly no real library would use this implementation, the iterative variant is both easier to understand and much faster.

6 Comments

I have mentioned the link of source.
Yes, it was a rhetorical question.
I think you are right there is a bug because all characters can't be NULL they would be zero. but if they are zero then also it's ok isn't it?
Characters can't be NULL, only pointers can. Characters are NUL and you're only guaranteed one at the end, the rest of the array could be filled with anything. And, BTW in almost all implementations, both NULL and NUL are actually zero.
@MAP NUL is defined as 0 by the ASCII specification. The C specification only talks about characters with value zero, not NUL.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.