在官方的文档中,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