C++ String strncpy() Function

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
Bounded copy

What You’ll Learn

The strncpy() function copies at most num characters from a source C-string into a destination buffer. It is often taught as a “safer” alternative to strcpy(), but beginners must learn its quirks: it may not add a null terminator, and it may zero-pad when the source is short.

01

Copy n Max

Limit from source.

02

Null Trap

May omit \0.

03

Zero Pad

If source short.

04

Return dest

Same pointer.

05

vs strcpy

Full vs bounded.

06

Manual \0

Often required.

Definition and Usage

In C++, strncpy() is declared in <cstring>. It writes up to num characters from source into destination. If the source string ends before num characters are copied, the remaining bytes up to num are filled with '\0' padding.

If the source is longer than or equal to num characters before its own terminator, strncpy copies exactly num bytes and may leave destination without a trailing '\0'. That is why printing or passing the result to functions expecting C-strings can misbehave unless you terminate manually.

💡
Beginner Tip

After strncpy(dest, src, n) when the buffer size is at least n + 1, add dest[n] = '\0' to force termination. Or copy at most n - 1 characters and always leave room for the terminator.

📝 Syntax

Function signature and a typical call:

C++
#include <cstring>

char* strncpy(char* destination, const char* source, size_t num);

// Example (buffer must hold num+1 if you null-terminate at [num]):
char dest[20];
strncpy(dest, "Hello, World!", 10);
dest[10] = '\0';  // manual terminator

Parameters

  • destination — writable buffer receiving the copy.
  • source — null-terminated C-string to copy from.
  • num — maximum number of characters to copy from source (may include padding behavior).

Return Value

Returns destination. The buffer content may or may not be a valid C-string until you terminate it yourself.

⚡ Quick Reference

FunctionCopiesNull-terminates?
strcpy()Full source + \0Yes (if buffer big enough)
strncpy()At most num bytesNot guaranteed
strncat()Append up to numYes
std::string =Full or assignAutomatic
Copy
strncpy(d, s, n)

Bounded copy

Terminate
d[n] = '\0'

When size n+1

Safer n
n = size - 1

Leave 1 byte

Include
#include <cstring>

Header file

Examples Gallery

Compile with g++ strncpy.cpp -std=c++17 -o strncpy. Every example shows explicit null termination when strncpy alone would not guarantee a printable C-string.

📚 Getting Started

Copy a limited prefix and terminate manually for printing.

Example 1 — Copy Ten Characters

Copy up to 10 bytes from "Hello, World!" and null-terminate at index 10.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* source = "Hello, World!";
    char destination[20];

    std::strncpy(destination, source, 10);
    destination[10] = '\0'; // required for safe printing

    std::cout << "Copied: " << destination << "\n";
    std::cout << "Length: " << std::strlen(destination) << "\n";

    return 0;
}

How It Works

Ten characters Hello, Wor are copied without the source null byte. Setting destination[10] makes the result a valid C-string for cout and strlen.

Example 2 — Source Shorter Than num

When source fits within the limit, strncpy zero-pads up to num bytes—and includes a terminator in the padded region.

C++
#include <iostream>
#include <cstring>

int main() {
    char dest[12];
    const char* source = "Hi";

    std::strncpy(dest, source, 8);
    dest[8] = '\0'; // good practice even after padding

    std::cout << "Text: \"" << dest << "\"\n";
    std::cout << "strlen: " << std::strlen(dest) << "\n";

    return 0;
}

How It Works

After copying Hi and its terminator, strncpy writes extra '\0' bytes until 8 total bytes are filled. The string still prints as Hi because the first null ends display.

📈 Practical Patterns

Compare with strcpy, wrap safely, and cap user input.

Example 3 — strncpy() vs strcpy()

strcpy always copies the full string when the buffer is large enough.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* source = "CodeToFun";
    char limited[20];
    char full[20];

    std::strncpy(limited, source, 4);
    limited[4] = '\0';

    std::strcpy(full, source);

    std::cout << "strncpy(4): " << limited << "\n";
    std::cout << "strcpy():   " << full << "\n";

    return 0;
}

How It Works

strncpy with a small limit truncates; strcpy copies everything including the terminator. Choose based on whether truncation is intentional.

Example 4 — Safe Copy Helper

Always leave one byte for '\0' and copy at most size - 1 characters.

C++
#include <iostream>
#include <cstring>

void copySafe(char* dest, std::size_t destSize, const char* src) {
    if (destSize == 0) {
        return;
    }
    std::strncpy(dest, src, destSize - 1);
    dest[destSize - 1] = '\0';
}

int main() {
    char buffer[8];
    copySafe(buffer, sizeof buffer, "LongUserName");

    std::cout << "Stored: " << buffer << "\n";
    std::cout << "Length: " << std::strlen(buffer) << "\n";

    return 0;
}

How It Works

A buffer of 8 bytes accepts at most 7 characters plus terminator. This pattern is a common beginner-friendly wrapper around raw strncpy.

Example 5 — Truncate User Input into a Label

Simulate storing a nickname in a fixed field for a high-score table.

C++
#include <iostream>
#include <cstring>

struct Player {
    char name[12];
    int score;
};

int main() {
    Player p{};
    p.score = 980;

    const char* input = "SuperStarGamer2026";
    std::strncpy(p.name, input, sizeof p.name - 1);
    p.name[sizeof p.name - 1] = '\0';

    std::cout << "Name:  " << p.name << "\n";
    std::cout << "Score: " << p.score << "\n";

    return 0;
}

How It Works

Eleven characters fit in name[12] with a terminator. Long input is truncated cleanly instead of overflowing the struct field.

🚀 Common Use Cases

  • Fixed-size struct fields — store names, codes, or titles with a max length.
  • Truncating external input — cap data from files, networks, or users.
  • Legacy C APIs — fill buffers expected by older libraries.
  • Teaching bounded I/O — step between unrestricted strcpy and std::string.
  • Partial copies — move exactly n characters without allocating new memory.

🧠 How strncpy() Works

1

Read source byte

Copy characters from source into destination.

Copy
2

Stop at num or \0

Stop after num bytes or when source ends—whichever rule applies per phase of the algorithm.

Limit
3

Pad if needed

If source ended early, write '\0' bytes until num total writes occur.

Pad
!

Return destination

You may still need to add '\0' manually when the copy used all num slots on a long source.

📝 Notes

  • If source length is ≥ num, destination may be not null-terminated.
  • If source length is < num, remaining bytes up to num are zero-filled.
  • num is a maximum from source, not the total destination buffer size.
  • Do not use on overlapping memory regions; use memmove instead.
  • Modern C++ favors std::string, std::string_view, or snprintf for clearer semantics.

⚡ Optimization

Zero-padding when source is short can write many unnecessary bytes if num is large. Prefer copying min(strlen(src), n-1) with an explicit terminator, or use higher-level string types. Avoid repeated strncpy on huge fixed fields when only a short prefix changes.

Conclusion

strncpy() limits how many characters come from source, but it is not a magic safety net. Always plan buffer size, understand padding, and add '\0' when the copy consumes the full limit on a long string.

Next, learn strpbrk() to find the first character in a C-string that matches any member of a given set.

💡 Best Practices

✅ Do

  • Copy at most bufferSize - 1 chars and set the last byte to '\0'
  • Wrap strncpy in a helper like copySafe
  • Prefer std::string in new C++ application code
  • Zero-initialize buffers when clarity matters (char buf[N]{})
  • Include <cstring> and use std::strncpy

❌ Don’t

  • Assume strncpy always produces a printable C-string
  • Pass sizeof(dest) as num without leaving terminator space
  • Call strlen on destination if it may be unterminated
  • Confuse strncpy (replace) with strncat (append)
  • Use huge num values that cause excessive zero-padding

Key Takeaways

Knowledge Unlocked

Five things to remember about strncpy()

Use these points whenever you copy into fixed char buffers.

5
Core concepts
02

May Lack \0

Terminate yourself.

Trap
🔢 03

Zero Pad

If source short.

Behavior
🔄 04

vs strcpy

Full vs limit.

Compare
🛡 05

size - 1

Safe pattern.

Pattern

❓ Frequently Asked Questions

strncpy() copies at most num characters from source into destination. If source is shorter than num, it may zero-pad the remaining bytes up to num. It returns destination. Unlike strcpy(), it does not always produce a null-terminated string when the copy fills all num slots.
char* strncpy(char* destination, const char* source, size_t num); Include <cstring>. destination must point to a buffer with at least num bytes when you rely on bounded copy semantics.
No. If source has num or more characters before '\0', strncpy copies exactly num bytes and may omit the terminator. You must add dest[num] = '\0' (when buffer size is num+1) or use a safer wrapper that always terminates.
Not by itself. It limits how many characters are read from source, but you must still size destination correctly and manually null-terminate when needed. Many production codebases prefer std::string, snprintf, or strcpy_s-style APIs instead of raw strncpy.
strcpy() copies the full source including '\0' and requires strlen(source)+1 bytes. strncpy() copies at most num characters and may leave destination unterminated or zero-padded. strcpy is simpler when the buffer is known big enough; strncpy adds a length cap.
If source ends before num characters are copied, the C standard requires strncpy to write additional '\0' bytes until num total bytes have been written. That padding can hide missing manual terminators but also wastes work on large num values.
Did you know?

Many coding standards discourage raw strncpy because of null-termination and padding surprises. The Linux kernel and numerous style guides recommend snprintf(dest, size, "%s", src) or platform bounds-checked functions instead.

Continue the String Functions Series

Copy with limits using strncpy(), then search with strpbrk().

Next: strpbrk() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful