Date: 2004oct22
Update: 2026apr27
Language: C/C++
Q. C/C++: The best and safest way to copy strings in C/C++
A.
BAD REASON
strcpy() no bounds checking
lstrcpy() ditto - Windows only
lstrcpyW() ditto - Windows only (Unicode)
strncpy() terminating NUL isn't guaranteed
GOOD REASON
strcpyn() bounds checking and terminating NUL guaranteed
strlcpy() ditto - BSD and gcc (Linux)
strscpy() ditto - Linux kernel
lstrcpyn() ditto - Windows only
lstrcpynW() ditto - Windows only (Unicode)
The Linux manual page for strcpy() says:
If the destination string of a strcpy() is not large enough (that is,
if the programmer was stupid/lazy, and failed to check the size before
copying) then anything might happen. Overflowing fixed length strings
is a favourite cracker technique.
Q. What about string concatenation?
A.
BAD REASON
strcat() no bounds checking
lstrcat() ditto - Windows only
lstrcatW() ditto - Windows only
GOOD REASON
strlcat() bounds checking and terminating NUL guaranteed - BSD, gcc
strcat_s() ditto - Windows only
Or use std::string or CString
---------------------
Here is a full string copy example that works on Windows and Linux
#include <stdio.h>
#include <string.h> // Has strlcpy() on Linux
#ifdef _WIN32
#include "windows.h" // For lstrcpyn() on Windows
#endif
void portable_strlcpy(char *dest, const char *src, const size_t maxChars) {
#ifdef _MSC_VER
lstrcpyn(dest, src, maxChars); // Windows
#else
strlcpy(dest, src, maxChars); // Linux
#endif
}
int main() { // Example use
char buf[100] = "Something";
portable_strlcpy(buf, "Hello", sizeof(buf));
printf("buf=%s\n", buf);
}
Outputs:
buf=Hello
---------------------
Here is a full string concatenate example that works on Windows and Linux
#include <stdio.h>
#include <string.h> // Has strlcat() on gcc, has strcat_s() on Windows
void portable_strlcat(char *dest, const char *src, const size_t size) {
#ifdef _WIN32
strcat_s(dest, size, src); // Windows
#else
strlcat(dest, src, size); // Linux
#endif
}
int main() {
char buf[200] = "";
portable_strlcat(buf, "one ", sizeof(buf));
portable_strlcat(buf, "two ", sizeof(buf));
portable_strlcat(buf, "three ", sizeof(buf));
printf("buf=%s<\n", buf);
}
Outputs:
buf=one two three <