在官方的文档中,http://www.cplusplus.com/refer…,例程的 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]
这样才能有稳定的输出
而另外,snprintf 则不需要 – 1
http://stackoverflow.com/questions/12275381/strncpy-vs-sprintf