strXcpy comparison
In the beginning, there was
void
.
As a C programmer you probably know strcpy()
, but hopefully strncpy()
, too.
But do you also know strlcpy()
(from BSD) and strscpy()
(from the Linux kernel)?
And do you know the suitable differences?
strcpy
char *strcpy(char *dest, const char *src);
Characteristics
- Will copy unknown number of characters from
*src
to*dst
until the first\0
character is reached. - The destination
*dst
must be large enough to hold the sting. - The trailing space of the destination is not touched.
- It returns
*dest
unmodified. - POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.
Example
#include <stdio.h>
#include <string.h>
static const char DEFAULT[] = "text";
static char dest[sizeof DEFAULT];
int main(int argc, char **argv) {
const char *src = argc > 1 ? argv[1] : DEFAULT;
char *res = strcpy(dest, src);
printf("source length=%zd\n", strlen(src));
printf("destination length=%zd\n", strlen(dest));
printf("returned pointer=dest+%ld\n", res - dest);
printf("last character[%zd]=0x%02x\n", sizeof dest - 1, dest[sizeof dest - 1]);
return 0;
}
Compilation
gcc -Wall -o strncpy strncpy.c
strncpy
char *strncpy(char *dest, const char *src, size_t n);
Characteristics
- Will copy up to
n
characters from*src
to*dst
until the first\0
character is reached. - If the destination
*dst
is not large enough, there will be no trailing\0
s. - The trailing space will be filled with
\0
. - It returns
*dest
unmodified. - POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.
Example
#include <stdio.h>
#include <string.h>
static const char DEFAULT[] = "text";
static char dest[sizeof DEFAULT];
int main(int argc, char **argv) {
const char *src = argc > 1 ? argv[1] : DEFAULT;
char *res = strncpy(dest, src, sizeof dest);
printf("source length=%zd\n", strlen(src));
printf("destination length=%zd\n", strlen(dest));
printf("returned pointer=dest+%ld\n", res - dest);
printf("last character[%zd]=0x%02x\n", sizeof dest - 1, dest[sizeof dest - 1]);
if (dest[sizeof dest - 1]) {
printf("TRUNCATED, Manually terminating string!\n");
dest[sizeof dest - 1] = '\0';
}
return 0;
}
Compilation
gcc -Wall -o strncpy strncpy.c
strlcpy
size_t strlcpy(char *dest, const char *src, size_t size);
Characteristics
- Will copy up to
n-1
characters from*src
to*dst
until the first\0
character is reached. - Will always terminate the string with one
\0
character. - The trailing space of the destination is not touched.
- It returns the length of
*src
. - BSD only!
Example
#include <stdio.h>
#include <string.h>
#include <bsd/string.h>
static const char DEFAULT[] = "text";
static char dest[sizeof DEFAULT];
int main(int argc, char **argv) {
const char *src = argc > 1 ? argv[1] : DEFAULT;
size_t len = strlcpy(dest, src, sizeof dest);
printf("source length=%zd\n", strlen(src));
printf("destination length=%zd\n", strlen(dest));
printf("returned len (of source)=%zd\n", len);
printf("last character[%zd]=0x%02x\n", sizeof dest - 1, dest[sizeof dest - 1]);
if (len >= sizeof dest)
printf("TRUNCATED!\n");
return 0;
}
Compilation
You need libbsd
::
apt-get install libbsd-dev
gcc -Wall -o strlcpy strlcpy.c -lbsd
strscpy
ssize_t strscpy(char *dest, const char *src, size_t count);
Characteristics
- Will copy up to
n-1
characters from*src
to*dst
until the first\0
character is reached. - Will always terminate the string with one
\0
character (ifcount > 0
). - The trailing space of the destination is not touched.
- Returns the number of characters copied excluding the terminating
\0
character or-E2BIG
. - Linux kernel only!
Example
#include <stdio.h>
#include <string.h>
#include "uapi/asm-generic/errno-base.h"
static const char DEFAULT[] = "text";
static char dest[sizeof DEFAULT];
ssize_t strscpy(char *dest, const char *src, size_t count);
int main(int argc, char **argv) {
const char *src = argc > 1 ? argv[1] : DEFAULT;
size_t len = strscpy(dest, src, sizeof dest);
printf("source length=%zd\n", strlen(src));
printf("destination length=%zd\n", strlen(dest));
printf("copied=%zd\n", len);
printf("last character[%zd]=0x%02x\n", sizeof dest - 1, dest[sizeof dest - 1]);
if (len == -E2BIG)
printf("TRUNCATED!\n");
return 0;
}
/* dummy definitions */
#define __must_check
#define __noreturn
#define __malloc
#define _ASM_EXTABLE(a, b)
#define barrier_data(a)
#define pr_emerg(a, b)
#define BUG(a)
#define BUG_ON(a)
/* from include/linux/kernel.h */
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
/* do not load Linux kernel headers */
#define _LINUX_BITOPS_H
#define _LINUX_LOG2_H
#define _LINUX_KERNEL_H
#define _ASM_X86_BUG_H
#include "../lib/ctype.c"
#include "../lib/string.c"
Compilation
You need the Linux source code::
apt-get install linux-source
gcc -Wall \
-I../linux/arch/x86/include \
-I../linux/include \
strscpy.c
Written on January 16, 2018