string is just an array (buffer) of chars. Basically, an array of 8-bit unsigned ints. And the last element in the array is '\0'. The actual array can be much bigger than the string occupying it, and strcat indeed requires that the dest is big enough to contain both the dest string and the source strings together. strcat is not a ready-to-use method like in higher level languages. It's use case looks like this:
char* buffer = malloc(strlen(string1) + strlen(string2) +1) Create a buffer that's big enough to contain both strings.
strpy(buffer, string1) Copy the first string to the buffer
strcat(buffer, string2) Append the second string to the buffer where the first string ends.
++ and -- operators allow a pointer to serve as enumerator. Think of those as .next() and .prev(). The caveat here is that they return (or accept) the value BEFORE moving the enumerator. This is critical here, this basically is what allows C to be so hard ;) If you want to recreate this in higher level, it'll be getAndNext() and setAndNext()
* is an accessor, working both ways, so it's enumerator's getValue() and setValue().
First block just skips the dest buffer until it reaches the end of the string in it - but NOT the end of the buffer.
while (*dest)
dest.next();
in pseudo-code is:
while (dest.get() != '\0')
dest.next();
That's because \0 is a real zero in the int meaning, and int zero is false in boolean meaning. Anything non-zero is true. That means -1, 42 and 'A' are just as true as 1. So in C we just skip the != 0 which is as pointless as writing != false in a language that has real booleans.
while (*dest++ = *src++)
;
Can be restated as:
while (dest.setAndNext(src.getAndNext()) != '\0')
or without the compounding:
char value;
do
{
dest.set(src.get());
value = src.get();
src.next();
dst.next();
}
while (value != '\0');
That's because in C an assignment has a value. So (*dest++ = *src++) ultimately returns the character that had been copied. It's like an inline function that copies, advances and then returns what was copied.
A pointer can legally point beyond the array. It's like enumerator that had reached the end and there is nothing more. The big difference is that a high-level enumerator can and will tell you that (via an exception), while a pointer will keep going even though it doesn't make any sense anymore. That's why both src and dest pointers are ++ed one time too many, but we don't care because we've took care to never use them after that.
rdest is simply saved position of where the buffer started. We can't return dest, because that enumerator had been used up and now it's at the end of the string, while we need to return the beginning. "r" probably stands for "return", because the whole point of this variable is to be returned.