mystrcpychar dest[20];
strcpy(dest, "Hello");
printf("%s\n", dest); // โ Hello
You like writing things multiple ways (your three Simple, readable. You've written loops exactly like this before. The Same as The two-pointer lockstep compressed into one line per iteration. This is the form you'll see in real C codebases. After lesson 4, you know exactly what This is the classic C trick. The loop condition does everything: copy a character, advance both pointers, test if the copied character was Every index Before any Create a single file with all four strcpy(dst, src) copies every character from src into dst, including the terminating '\0'. It overwrites whatever was in dst before.strcat
strcat appends โ it must find the end of dest first, then copy. strcpy just copies from the beginning โ no search needed. That's one less act, which makes it the cleaner place to practice the two-pointer idiom.
Three ways to write it
mystrlen implementations proved that). Here are three ways to do mystrcpy, each teaching something different.Version 1 โ index form (the one you already know)
void mystrcpy_v1(char *dst, const char *src) {
int i = 0;
while (src[i] != '\0') {
dst[i] = src[i];
i++;
}
dst[i] = '\0'; // copy the terminator
}'\0' is copied after the loop โ the loop stops at the terminator, and the explicit line seals the copy.Version 2 โ pointer form (expanded, from lesson 2)
void mystrcpy_v2(char *dst, const char *src) {
char *p = dst;
const char *q = src;
while (*q != '\0') {
*p = *q;
p++;
q++;
}
*p = '\0'; // seal
}mystrcat's Act 2, but starting from position 0 instead of the end. No Act 1 needed โ the write pointer starts at the beginning. Same three-line lockstep you've been practicing.Version 3 โ compact form (from lesson 4)
void mystrcpy_v3(char *dst, const char *src) {
while (*src != '\0') {
*dst++ = *src++;
}
*dst = '\0';
}*dst++ = *src++ expands to.Bonus โ version 3b (the clever one-liner)
void mystrcpy_v3b(char *dst, const char *src) {
while (*dst++ = *src++)
; // empty body โ all the work is in the condition
}'\0' (i.e. zero). When '\0' is copied, the condition is false and the loop exits โ after writing the terminator into dst. No separate seal line needed.while condition. A newcomer sees it and thinks "that's an empty loop โ it does nothing." Use version 3 in your own code until the one-liner reads as naturally as English. For now, know it exists, don't write it.
See them side by side
while (src[i] != '\0') {
dst[i] = src[i];
i++;
}
dst[i] = '\0';while (*src != '\0') {
*dst++ = *src++;
}
*dst = '\0';i is a pointer offset. src[i] โก *(src + i). The pointer form just keeps the pointer moving instead of recalculating src + i each time. Same work, less arithmetic.The safety checklist (lesson 1, again)
strcpy โ hand-rolled or library โ the One Principle applies:
dst have real storage? Must be an array or malloc'd memory.strlen(src) + 1 bytes minimum. The +1 is for the '\0'.char dest[20];
mystrcpy(dest, "Hello"); // strlen("Hello") + 1 = 6 โค 20 โ
char small[4];
mystrcpy(small, "Hello"); // 6 > 4 โ UB, buffer overflowCheck yourself
โ Why doesn't
mystrcpy need an "Act 1" (find the end)?Show answer
Because strcpy copies from the beginning of dst, overwriting everything. strcat needs to find the end because it's appending โ it must know where the existing data stops. strcpy starts at position 0 unconditionally. That's the only structural difference.
โก In version 3b (
while (*dst++ = *src++);), when exactly is the '\0' copied?Show answer
On the last iteration โ when src points at '\0'. The expression *dst++ = *src++ copies that '\0' into dst, advances both pointers, and yields '\0' (which is 0 = false). The while condition is false โ loop exits. The terminator has already been written before the test. That's why no separate *dst = '\0'; is needed.
โข What's the return type of the real
strcpy?Show answer
It returns char * โ a pointer to the destination. This lets you chain calls: strcpy(buf, strcpy(buf2, "hello")); (copy "hello" into buf2, then copy buf2 into buf). Most people don't chain it, but the return value is part of the interface. Check cppreference.
โฃ Can
strcpy's source and destination overlap?Show answer
No โ undefined behavior. Example: strcpy(buf, buf + 2); โ the source starts inside the destination. As strcpy writes, it may overwrite source characters it hasn't read yet. The safe version for overlapping regions is memmove, which handles overlaps correctly.
๐ ๏ธ Hands-on โ write all four versions and test them
mystrcpy implementations. Call each one and verify identical output:
mystrcpy_v1 (index), v2 (expanded pointer), v3 (compact pointer), and v3b (one-liner).main, declare a char dest[20] for each call. Copy "Hello, world!" into each.Hello, world!"" into each. Does each version handle it correctly? (It should โ the loop body never executes, and only the terminator is written.)strcpy from scratch in four forms โ index, expanded pointer, compact pointer, and the one-liner. You see that every string-copy function is the same two-pointer lockstep underneath. And you know the safety rule: strlen(src) + 1 bytes must fit in dst.
strcpy return char*?", "when would I use memmove instead?", "can I write mystrcpy with strlen instead of a loop?" โ type it and we'll dig in. After this, you're ready for malloc.
ยท cppreference: strcpy โ the real signature, return value, and overlap restriction.
ยท cppreference: memmove โ the safe version for overlapping copies.
ยท Beej's Guide to C Programming โ strings and pointers.
ยท Companion cheat sheet ยท Lesson 4: *p++ = *q++