Stan Milam said:
My favorite way of doing this is:
strncpy( dest, cstring + offset, count )[count] = '\0';
It works because strncpy() returns the address of the dest argument.
cool. ;-)
Can someone give an example that strncpy() would be safer than strcpy() ?
#include <stdio.h>
void func(const char *str)
{
char buff[10];
strcpy(buff, str);
printf("%s\n", buff);
}
int main(int argc, char **argv)
{
if (argc > 1)
func(argv[1]);
return 0;
}
If the user runs this with parameter "1234567890", the buffer will
overflow (10 characters plus the terminating '\0'), as it will with a
longer string. In the Real World(tm) user input can't be guaranteed to
be right. If the strcpy were replaced by
strncpy(buff, str, 9)[9[ = '\0';
the program would be safe. (In practice, of course, you might want to
detect the overflow and report it as an error, and to use sizeof(buff)-1
instead of an explicit value.)
Should we never use strcpy() ?
strcpy() is completely safe to use /if/ you know that the string will
fit. Most of the time in my programs I know that the string will fit
because I have done checks elsewhere, or because I have just allocated
memory to the size of the string:
char *strDup(const char *str)
{
char *p = malloc(strlen(str) + 1);
if (p)
return strcpy(p, str);
return NULL;
}
Note that strcat also has the problem that the buffer can overflow, and
it's messy and wasteful to use strncat to detect that (since strncat
takes the number of characters to be copied not the length of the
buffer, so you still have to do strlen(buff) to determine whether the
string will fit).
Also, strncpy() will pad out the rest of the buffer with nul ('\0')
characters. Most of the time this is wasteful, especially if using a
big buffer with a small source string many times.
Because of these faults, the functions strlcpy() and strlcat() were
introduced in OpenBSD 2.4, and many of us hope that they will be
incorporated into a future C standard revision. See
http://www.courtesan.com/todd/papers/strlcpy.html
for example (the functions are easy to write, or you can use the OpenBSD
source under their Free Software licence).
Chris C