Question

How to Concatenate Strings Safely in C

cstringconcatenation

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:

  • destination must be a writable character array
  • destination must already contain a valid null-terminated string
  • destination must 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.

Take Quiz

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

  • message is 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 message at its null terminator
  • starts copying characters from name
  • writes B, o, b, and \0 at 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.

Take Quiz

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:

  • message does not begin as a valid null-terminated string
  • strcat() 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 const does not make memory writable
  • it only hides the warning

Avoid this entirely.

Comparisons

ApproachBest forProsCons
strcat()Appending to an existing writable string bufferSimple, standard CEasy to overflow buffer, destination must already contain a string
strcpy() + strcat()Building a string in stepsClear for simple casesMultiple calls, still unsafe if size is wrong
snprintf()Formatting a final string from piecesSafer, readable, handles numbers and stringsRequires format string knowledge
Dynamic allocation + snprintf()Unknown final size at compile timeFlexibleMust manage memory manually

strcat() vs snprintf()

Featurestrcat()snprintf()
Appends to existing stringYesNot directly
Needs pre-initialized destinationYesNo
Includes buffer size in callNoYes
Good for formatting mixed dataLimitedYes
Usually easier to read for full message creationNoYes

For most beginner and production cases where you are combining literals and variables into one message, snprintf() is the better choice.

Take Quiz

Cheat Sheet

Quick rules

  • strcat(dest, src) appends src to dest
  • dest must be writable
  • dest must already be a null-terminated string
  • dest must 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 repeated strcat()
  • 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.

Take Quiz

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
Take Quiz

Keep learning

Related questions

View more