How strcpy and strncpy Handle Null Termination in C
In C programming, strcpy and strncpy are
standard library functions used to duplicate strings, but they differ
fundamentally in how they enforce buffer boundaries and null-character
(\0) termination. While strcpy unconditionally
appends a null terminator at the expense of buffer overflow protection,
strncpy restricts writing to a maximum byte count \(n\), introducing nuances where strings may
be left unterminated or padded excessively. Understanding these boundary
behaviors is essential for writing safe, bug-free C code.
The Behavior of strcpy
The strcpy function follows a simple contract: it copies
characters from a source string (src) into a destination
buffer (dest) until it encounters the source's terminating
null byte (\0), which it also copies.
char *strcpy(char *dest, const char *src);- Termination Guarantee:
strcpyalways null-terminates the destination string, provided the operation completes. - Boundary Handling: It completely ignores the
allocated capacity of
dest. Ifsrccontains more characters thandestcan hold,strcpywrites past the end of the destination array. This results in undefined behavior, memory corruption, and severe security vulnerabilities such as buffer overflows.
The Behavior of strncpy
To prevent buffer overruns, strncpy introduces a third
parameter, n, which specifies the maximum number of bytes
to write to the destination.
char *strncpy(char *dest, const char *src, size_t n);However, strncpy was originally designed for fixed-width
directory entries in early Unix systems rather than general string
safety, leading to two distinct termination boundary conditions:
1. Truncation Leaves the Buffer Unterminated
If the length of src is equal to or greater than
n, strncpy copies exactly n bytes
and halts. It does not append a null terminator. As a result,
dest contains a non-terminated character sequence. Passing
this sequence to functions that expect standard C strings (such as
printf("%s", dest) or strlen(dest)) will cause
them to read past the buffer boundary until they encounter an arbitrary
\0 in memory.
2. Excessive Zero-Padding
If the length of src is strictly less than
n, strncpy writes the string and its null
terminator, and then continues writing \0 bytes until the
entire count of n bytes has been filled. While this ensures
termination, writing zero-bytes across large buffers introduces an
unnecessary performance overhead.
Key Differences at a Glance
| Feature | strcpy |
strncpy |
|---|---|---|
| Bound Checking | None | Limited to \(n\) bytes |
| Null Termination | Always appends \0 |
Only appends \0 if
strlen(src) < n |
| Overflow Risk | High (unbounded write) | Low (bounded by \(n\)) |
| Unterminated String Risk | Low (provided memory allows) | High (when
strlen(src) >= n) |
| Padding | None | Pads unused bytes up to \(n\) with \0 |
Ensuring Safe String Termination
To prevent unterminated buffers when using strncpy,
developers must manually enforce termination at the boundary:
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';Alternatively, modern C development often avoids both functions in
favor of safer alternatives such as snprintf, which
guarantees null termination whenever the buffer size is greater than
zero:
snprintf(dest, sizeof(dest), "%s", src);