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.
Fundamentals
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.
Foundation
📝 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.
Cheat Sheet
⚡ Quick Reference
Function
Copies
Null-terminates?
strcpy()
Full source + \0
Yes (if buffer big enough)
strncpy()
At most num bytes
Not guaranteed
strncat()
Append up to num
Yes
std::string =
Full or assign
Automatic
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
Hands-On
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.
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;
}
📤 Output:
Text: "Hi"
strlen: 2
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.
Eleven characters fit in name[12] with a terminator. Long input is truncated cleanly instead of overflowing the struct field.
Applications
🚀 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.
Important
📝 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.
Performance
⚡ 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.
Wrap Up
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.
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
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about strncpy()
Use these points whenever you copy into fixed char buffers.
5
Core concepts
📝01
Max n Copy
Bounded read.
Basics
⚠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.