我知道strncpy是strcpy的一个更安全的版本,正如here所说的那样。
但是,当我想从src复制到dst并且dst不是一个干净的缓冲区时,我会得到不想要的结果,这是strcpy可以避免的。
char *p = "123";
char a[10] = "aaaaaa";
strncpy(a,p,strlen(p));
printf("%s\n", a); // 123aaa
strcpy(a,p);
printf("%s\n", a); // 123 <- desired output, as the trailing a's are garbage在我的实际案例中,我知道strlen(src) < sizeof(dst) (至少,如果不是这样的话,程序会很快崩溃),所以我可以安全地使用strcpy。
但是,如果strncpy是我应该使用的,那么必须在dst[strlen(src)] = '\0'之后添加以避免垃圾(或者更好的做法是预先插入缓冲区)?
发布于 2018-09-06 15:14:46
strncpy的第三个参数表示目标缓冲区的大小。当它填充时,它不会按设计添加空终止字符。
如果您有足够的空间作为终止符,并且您坚持使用strncpy,那么只需传递strlen(p) + 1,这样它就不会假定它耗尽了目标缓冲区。
就像很多人已经注意到的那样。这种对strncpy的使用违背了目的,而且实际上也不比对strcpy的简单调用更好。strncpy的唯一实际用途是,如果您想要覆盖字符串的一部分(这是您偶然发现的用例)。虽然这也是值得怀疑的用途..。
发布于 2018-09-06 16:40:13
如何正确使用strncpy?
当代码需要将字符串复制到目标,并允许结果终止或完全复制时,请使用sizeof destination作为size参数:
char a[10];
// strncpy(a,p,strlen(p));
strncpy(a, p, sizeof a);
// printf("%s\n", a);
printf("%.*s\n", (int) sizeof a, a);当代码希望通过strncpy()复制字符串并检测内存不足问题或需要空字符'\0'填充时,也可以使用sizeof destination。
char a[10];
strncpy(a, p, sizeof a);
if (a[sizeof a - 1] != '\0') {
// insufficient memory
// Maybe set last last character to the null character
a[sizeof a - 1] == '\0';
// or other more robust handling
return ERROR_INSUFFICIENT_MEMORY;
}否则不要使用strncpy()
当不需要空字符strncpy()填充时,有更有效的方法来检测内存不足。strncpy()零填充未复制缓冲区的其余部分(如果有的话)。以下消耗大量的时间零填充,只是为了提供一个不足的检查。
char a[1000];
strncpy(a, "abc", sizeof a);
if (a[sizeof a - 1] != '\0') {
....更好的替代方案采用strlen(), strlcpy(), memcpy()。@Deduplicator。
另见strncpy or strlcpy in my case。
对于标准的C库一行,代码可以使用snprintf()和一行错误检测。一个好的编译器应该分析snprintf(a, sizeof a, "%s", p)并发出高效的代码。
// Copy with no overflow.
// 'a' is always null character terminated.
int len = snprintf(a, sizeof a, "%s", p);
if (len < 0 || (unsigned) len >= sizeof a) Report_truncated_copy();发布于 2018-09-06 15:58:32
strncpy()实际上不是一个字符串函数;相反,它处理非零字符的零填充序列,这些字符加在一起有一个已知的固定长度。例如,它是填充数据结构的正确工具,这些数据结构随后被发送到其他程序、外部程序或持久化程序,以避免数据泄漏。
试图在其非常专门的利基之外使用它,会导致可怕的扭曲和低效的代码。
有更合适的方法来解决这个问题,比如strlcpy()和/或手动使用strlen()和memcpy()。
https://stackoverflow.com/questions/52207214
复制相似问题