Question
I'm working in C and need to concatenate several strings.
Right now I have code like this:
Copymessage = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
This causes a segmentation fault at runtime. Why does that happen in C, and what is the correct way to concatenate string literals and variables safely?
Short Answer
By the end of this page, you will understand why strcat() crashes when used with string literals in C, how C strings are stored in memory, and how to safely build combined strings using writable character arrays or snprintf(). You will also learn common mistakes, safer alternatives, and practical patterns used in real C programs.
Concept
In C, a string is usually represented as a null-terminated array of characters.
For example:
char name[] = "Sam";
This creates a writable array in memory:
'S' 'a' 'm' '\0'
But a string literal like this:
"TEXT "
is not a writable destination for strcat(). Even though it looks like a string value, it is stored in read-only memory on many systems. Trying to modify it causes undefined behavior, which often appears as a segmentation fault.
Why strcat() fails here
The function strcat(destination, source) appends source to the end of destination.
That means:
destinationmust be a writable character arraydestinationmust already contain a valid null-terminated stringdestinationmust have enough extra space to hold the result
So this is wrong:
strcat("TEXT ", var);
because "TEXT " is a string literal, not a writable buffer.
Why this matters
String handling is one of the most important and error-prone parts of C programming. Unlike higher-level languages, C does not automatically resize strings. You must:
- allocate enough memory yourself
- use writable buffers
- avoid writing past the end of the buffer
- ensure strings remain null-terminated
If you do not, your program may crash, corrupt memory, or become insecure.
Mental Model
Think of strcat() like writing extra text onto a label.
- A string literal is like text printed on a glass wall: you can read it, but you should not write on it.
- A character array buffer is like a whiteboard: you can write on it, erase it, and add more text if there is space.
strcat() only works when the first argument is a whiteboard with enough room left.
If you try to append onto a glass wall, it breaks. In C, that "break" often shows up as a segmentation fault.
Syntax and Examples
The basic syntax of strcat() is:
strcat(destination, source);
Correct example with a writable buffer
#include <stdio.h>
#include <string.h>
int main(void) {
char var[] = "world";
char message[100] = "TEXT ";
strcat(message, var);
printf("%s\n", message);
return 0;
}
Output:
TEXT world
Why this works
messageis a writable character array- it starts with the string
"TEXT " - it has enough space for the extra characters in
var
Concatenating multiple pieces
#include <stdio.h>
#include <string.h>
int main(void) {
char foo[] = "Alice";
char bar[] = "Engineer";
char message2[100] = "TEXT ";
strcat(message2, foo);
strcat(message2, " TEXT ");
strcat(message2, bar);
printf("%s\n", message2);
return 0;
}
Output:
TEXT Alice TEXT Engineer
Safer alternative: snprintf()
In many cases, snprintf() is easier and safer than repeated strcat() calls.
#include <stdio.h>
int main(void) {
char foo[] = "Alice";
char bar[] = "Engineer";
char message[100];
snprintf(message, sizeof(message), "TEXT %s TEXT %s", foo, bar);
printf("%s\n", message);
return 0;
}
This is often preferred because it builds the final string in one step and respects the buffer size.
Step by Step Execution
Consider this example:
#include <stdio.h>
#include <string.h>
int main(void) {
char name[] = "Bob";
char message[20] = "Hello ";
strcat(message, name);
printf("%s\n", message);
return 0;
}
Step-by-step
1. Create name
char name[] = "Bob";
Memory contains:
'B' 'o' 'b' '\0'
2. Create message
char message[20] = "Hello ";
Memory begins as:
'H' 'e' 'l' 'l' 'o' ' ' '\0' ...extra unused space...
3. Call strcat(message, name)
strcat() does this:
- finds the end of
messageat its null terminator - starts copying characters from
name - writes
B,o,b, and\0at the end
Now message contains:
'H' 'e' 'l' 'l' 'o' ' ' 'B' 'o' 'b' '\0'
4. Print the result
printf("%s\n", message);
Output:
Hello Bob
What would go wrong with a literal?
If you wrote:
strcat("Hello ", name);
then strcat() would try to append onto read-only memory. That is invalid and may crash immediately.
Real World Use Cases
String concatenation in C appears in many practical situations:
Building log messages
snprintf(logLine, sizeof(logLine), "ERROR: %s", errorMessage);
Creating file paths
snprintf(path, sizeof(path), "%s/%s", directory, filename);
Formatting API or protocol messages
snprintf(request, sizeof(request), "GET /users/%s HTTP/1.1\r\n", userId);
Combining user-facing text
snprintf(greeting, sizeof(greeting), "Hello, %s!", username);
Generating SQL or command strings carefully
C programs often assemble strings for tools, configuration, or data output. In all of these cases, developers must avoid buffer overflows and must never treat string literals as writable buffers.
Real Codebase Usage
In real C codebases, developers usually avoid chaining strcat() on temporary pieces and instead use clearer, safer patterns.
Common patterns
Use snprintf() for formatting
This is very common when combining literals and variables:
char message[256];
snprintf(message, sizeof(message), "User: %s, Age: %d", name, age);
Why it is popular:
- one call instead of many
- easier to read
- respects buffer size
- supports numbers and strings together
Build strings incrementally in a buffer
Sometimes code appends piece by piece:
char buffer[256] = "";
strcat(buffer, prefix);
strcat(buffer, name);
strcat(buffer, suffix);
This works only if the buffer is large enough.
Guard against overflow
Real projects often validate lengths before concatenating:
if (strlen(prefix) + strlen(name) + 1 < sizeof(buffer)) {
strcpy(buffer, prefix);
strcat(buffer, name);
}
Use dynamic allocation when size is unknown
If the final size depends on input, code may allocate memory first:
size_t len = strlen(foo) + strlen(bar) + strlen("TEXT ") + strlen(" TEXT ") + 1;
char *message = malloc(len);
if (message != NULL) {
snprintf(message, len, "TEXT %s TEXT %s", foo, bar);
}
Prefer readability over clever nesting
This is hard to read and unsafe:
strcat(strcat(a, b), c);
In real code, developers usually write separate steps or use snprintf().
Common Mistakes
1. Using a string literal as the destination
Broken code:
strcat("TEXT ", var);
Why it fails:
- string literals are not writable destinations
Fix:
char message[100] = "TEXT ";
strcat(message, var);
2. Not allocating enough space
Broken code:
char message[10] = "TEXT ";
strcat(message, "very long value");
Why it fails:
- the result does not fit in the buffer
- this causes buffer overflow and undefined behavior
Fix:
- make the buffer larger
- or calculate the needed size
- or use
snprintf()
3. Forgetting to initialize the destination string
Broken code:
char message[100];
strcat(message, "Hello");
Why it fails:
messagedoes not begin as a valid null-terminated stringstrcat()cannot find the correct end
Fix:
char message[100] = "";
strcat(message, "Hello");
4. Chaining strcat() without thinking about readability or safety
Broken style:
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Problems:
- modifies literals
- difficult to read
- hard to debug
Better:
char message2[100];
snprintf(message2, sizeof(message2), "TEXT %s TEXT %s", foo, bar);
5. Assuming const char * means writable string storage
Broken idea:
const char *s = "Hello";
strcat((char *)s, "!");
Why it is wrong:
- casting away
constdoes not make memory writable - it only hides the warning
Avoid this entirely.
Comparisons
| Approach | Best for | Pros | Cons |
|---|---|---|---|
strcat() | Appending to an existing writable string buffer | Simple, standard C | Easy to overflow buffer, destination must already contain a string |
strcpy() + strcat() | Building a string in steps | Clear for simple cases | Multiple calls, still unsafe if size is wrong |
snprintf() | Formatting a final string from pieces | Safer, readable, handles numbers and strings | Requires format string knowledge |
Dynamic allocation + snprintf() | Unknown final size at compile time | Flexible | Must manage memory manually |
strcat() vs snprintf()
| Feature | strcat() | snprintf() |
|---|---|---|
| Appends to existing string | Yes | Not directly |
| Needs pre-initialized destination | Yes | No |
| Includes buffer size in call | No | Yes |
| Good for formatting mixed data | Limited | Yes |
| Usually easier to read for full message creation | No | Yes |
For most beginner and production cases where you are combining literals and variables into one message, snprintf() is the better choice.
Cheat Sheet
Quick rules
strcat(dest, src)appendssrctodestdestmust be writabledestmust already be a null-terminated stringdestmust have enough free space- never use a string literal as
dest
Safe pattern with strcat()
char message[100] = "Hello ";
strcat(message, name);
Safe pattern with snprintf()
char message[100];
snprintf(message, sizeof(message), "Hello %s", name);
Common bad code
strcat("Hello ", name); // wrong
Common good code
char buf[100] = "Hello ";
strcat(buf, name);
Remember
- string literal: readable text, not writable storage
- character array: writable storage
snprintf()is often safer than repeatedstrcat()- always leave room for the final
\0
FAQ
Why does strcat("TEXT ", var) crash in C?
Because "TEXT " is a string literal, and strcat() tries to modify it. String literals are not valid writable destinations.
Can I concatenate string literals directly in C?
Only at compile time when they are written next to each other:
char s[] = "Hello " "World";
This becomes "Hello World". But that is different from runtime concatenation.
What is the safest way to combine strings in C?
For many cases, use snprintf() with a properly sized buffer.
Do I always need a character array for strcat()?
Yes. The destination must be writable memory containing a valid null-terminated string.
Is const char * safe to use with strcat()?
Not as the destination. A const char * points to data you should not modify.
How do I know how large my buffer should be?
Add the lengths of all strings you want to combine, then add 1 for the null terminator.
Can I use malloc() for string concatenation?
Yes. If the final size is not fixed, allocate enough memory dynamically and then write into it with snprintf() or copy/append functions.
Mini Project
Description
Create a small C program that builds a status message from several pieces of text, such as a prefix, a username, and a role. This project demonstrates the correct way to combine strings without writing into string literals and without overflowing buffers.
Goal
Build and print a complete message safely using a writable buffer and snprintf().
Requirements
- Create variables for a username and a role
- Build a final message that includes fixed text and both variables
- Store the result in a writable character buffer
- Print the final message to the console
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.