在官方的文档中,http://www.cplusplus.com/reference/cstring/strncpy/,例程的 strncpy 的用法是:
/* strncpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]= "To be or not to be";
char str2[40];
char str3[40];
/* copy to sized buffer (overflow safe): */
strncpy ( str2, str1, sizeof(str2) );
/* partial copy (only 5 chars): */
strncpy ( str3, str2, 5 );
str3[5] = '\0'; /* null character manually added */
puts (str1);
puts (str2);
puts (str3);
return 0;
}
注意到第 12 行,最后的参数是直接 sizeof,这样虽然可以防止溢出,但是其实还是 printf strlen 之类的不安全的,看看这个例子:
#include <stdio.h>
#include <string.h>
int main() {
char str[3];
memset(str, 0, sizeof(str));
strncpy(str, "testtest", sizeof(str));
printf("[%s][%d]\n", str, strlen(str));
return 0;
}
看看输出:
$ ./a.out
[tes][6]
$ ./a.out
[tesx][6]
$ ./a.out
[tesn][6]
$ ./a.out
[tes][6]
$ ./a.out
[tes][6]
$ ./a.out
[tes*][6]
$ ./a.out
[tes¡][6]
$ ./a.out
[tesP][6]
$ ./a.out
[tes][6]
可以看到,最后那个 char 是不确定的,而且 strlen 也出错,那么,稳妥的做法应该是 -1
#include <stdio.h>
#include <string.h>
int main() {
char str[3];
memset(str, 0, sizeof(str));
strncpy(str, "testtest", sizeof(str)-1);
printf("[%s][%d]\n", str, strlen(str));
return 0;
}
$ ./a.out
[te][2]
$ ./a.out
[te][2]
$ ./a.out
[te][2]
$ ./a.out
[te][2]
这样才能有稳定的输出
历史评论
ZRJ (2013-09-29 21:13:02):
而另外,snprintf 则不需要 - 1
ZRJ (2014-01-27 17:17:24):
http://stackoverflow.com/questions/12275381/strncpy-vs-sprintf