strcat is one of the first string functions every C programmer learns — and one of the most feared, because it’s a buffer overflow waiting to happen. But is it always? This question from our C Programming Quiz App checks whether you can tell a safe strcat from a dangerous one by reading the declaration.
The Quiz Question
char s[10] = "abc";
strcat(s, "def");
printf("%s", s);
What is printed by this code?
- abc
- def
- abcdef
- Undefined behavior
The Correct Answer: abcdef
strcat(dest, src) finds the null terminator at the end of dest, copies src starting there (terminator included), and returns dest. Here the result needs strlen("abc") + strlen("def") + 1 = 7 bytes, and s has 10 — plenty of room. Verified on gcc 13.3 and Apple clang 21, clean under -ansi -Wall -Wextra:
$ gcc -ansi -Wall -Wextra cat.c && ./a.out abcdef strlen after = 6
Why Each Wrong Answer Is Wrong
Why not “abc”?
strcat modifies dest in place — it doesn’t build a new string and hand it back for you to ignore. After the call, s itself contains "abcdef".
Why not “def”?
That would be replacement, which is strcpy‘s job. strcat is con-cat-enation: it preserves the existing content and appends after it.
Why not undefined behavior?
This is the trap for readers who’ve (rightly) been taught to distrust strcat. It is UB when the destination is too small — but here the declaration says char s[10], and 7 ≤ 10. The partial-initializer rule even zero-fills the unused tail. To show what the wrong version looks like, we shrank the buffer to char s[4] (exactly fits “abc” with its terminator, no spare room):
char s[4] = "abc";
strcat(s, "def"); /* needs 7 bytes, has 4 — UB */
$ ./a.out (gcc 13.3, Linux) *** stack smashing detected ***: terminated Aborted (core dumped) $ ./a.out (Apple clang 21, macOS) Trace/BPT trap (fortify check)
Both runtimes catch this particular overflow, but that’s luck, not a guarantee — a heap buffer or a bigger overrun can silently corrupt neighboring data instead. The lesson: strcat‘s safety is decided at the declaration, not at the call site.
Sizing the Destination — the Only Rule That Matters
strcat needs strlen(dest) + strlen(src) + 1 bytes of capacity in dest. When the strings aren’t compile-time constants, you can’t eyeball it — either check first, or use a bounded alternative:
/* bounded append, always terminated */
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", src);
strncat(dest, src, n) also exists, but its n counts the characters to append — not the buffer size — and it’s a recurring source of off-by-one bugs. snprintf takes the whole remaining buffer size and always terminates, which makes it the harder-to-misuse choice. If you want to see what strcat does under the hood, we’ve implemented concatenation from scratch.
Frequently Asked Questions
What does strcat do in C?
It appends the source string to the end of the destination string in place: it locates the destination’s null terminator, copies the source there (including its terminator), and returns the destination pointer.
When is strcat undefined behavior?
When the destination array doesn’t have room for the combined string plus one terminator byte, or when either argument isn’t a properly null-terminated string, or when the strings overlap. The capacity rule is strlen(dest) + strlen(src) + 1 ≤ destination size.
Should I use strcat or strncat or snprintf?
Prefer snprintf for bounded appends — its size argument is the whole remaining buffer and the result is always terminated. strncat‘s count is the number of characters to append (not buffer size), which is easy to get wrong. Plain strcat is fine only when the capacity is provably sufficient, as in this quiz question.
Related Reading
- String Functions in C – Complete Reference
- C Program to Concatenate Two Strings
- Copy and Concatenate Strings Without Standard Functions
- strlen in C – Why strlen(“hello”) Is 5
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #107 in the C Programming Quiz App — 155 questions with explanations covering arrays, strings, pointers, and more.
Download on Google Play →