A char
is a small integer type (a byte), which can hold just a single encoded character, not a string. Strings in C don't have a dedicated type, they're just defined as a sequence of characters, ending with a 0
byte. So, you naturally store strings in arrays of char
. E.g. the array
char str[30];
Can store a string of up to 29 characters (one more is needed for the terminating 0
).
Furthermore, you have to know that arrays can't be passed to or returned from functions in C. Instead, pointers are used. If you write arrays as function arguments or return values, these types are automatically adjusted to the corresponding pointer types. It's common to say the array "decays" as a pointer. So, in your code, you attempt to return an array. Instead, a pointer to the first array element is returned. Because this array is local to your function, it doesn't exist any more after the return, so you are returning an invalid pointer.
That's why the library function strcat
expects the caller to give a pointer to the result, instead of returning the result. A typical simple strcat
function could look like this (not the original, returning nothing here to make the code simple):
void mystrcat(char *s, const char *append)
{
while (*s) ++s; // search end of s
while ( (*s++ = *append++) ); // copy until end of append
}
To understand this code, you have to know that 0
is false in C when evaluated in a boolean context, and any other value is true. ++
increments, so applied to pointers, moves them to point to the next element. Therefore, this code examines each character in *s
until it finds a 0
byte and then starts copying characters from *append
there until the 0
byte in *append
is hit.
If you absolutely want to return the result, you have to dynamically allocate memory for it in your function. This could look like the following:
char *concatenate(const char *s1, const char *s2)
{
size_t resultlen = strlen(s1) + strlen(s2) + 1; // one more for the 0 byte
char *result = malloc(resultlen);
if (!result) return 0; // allocation failed, out of memory
char *p = result;
while ( (*p = *s1++) ) ++p; // copy from s1 until 0
while ( (*p++ = *s2++) ); // copy from s2 until 0
return result;
}
Of course, in this case, the caller has to free()
the result when it's no longer needed.