我知道strncpy
是这里所说的更安全的strcpy
版本。
但是,当我想从src
复制到dst
并且dst
不是一个干净的缓冲区时,我得到不需要的结果,这可以通过strcpy
来避免:
char *p = "123";
char a[10] = "aaaaaa";
strncpy(a,p,strlen(p));
printf("%sn", a); // 123aaa
strcpy(a,p);
printf("%sn", a); // 123 <- desired output, as the trailing a's are garbage
在我的实际情况下,我知道strlen(src) < sizeof(dst)
(至少,如果不是这种情况,程序会崩溃得更快(,所以我可以安全地strcpy
.
但是,如果strncpy
是我应该使用的,那么我是否必须在dst[strlen(src)] = ' '
后添加以避免垃圾(或者更好的是,事先初始化缓冲区?
strncpy
的第三个参数用于表示目标缓冲区的大小。当它填满它时,它不会在设计中添加 null 终止字符。
如果你有足够的空间来容纳终结者,并且你坚持要strncpy
,只需传递strlen(p) + 1
,这样它就不会认为它耗尽了目标缓冲区。
就像现在已经注意到的许多人一样。这种strncpy
的使用违背了目的,真的不比简单的strcpy
调用好。strncpy
的唯一实际用途是,如果要就地覆盖字符串的一部分(这是您偶然发现的用例(。虽然这也是有问题的用途...
如何正确使用 strncpy?
当代码需要将字符串复制到目标并容忍结果不是null 字符终止或完全复制时,请使用 size 参数的sizeof destination
:
char a[10];
// strncpy(a,p,strlen(p));
strncpy(a, p, sizeof a);
// printf("%sn", a);
printf("%.*sn", (int) sizeof a, a);
当代码想要复制字符串并通过strncpy()
检测内存不足问题或需要空字符' '
填充时,也使用sizeof destination
。
char a[10];
strncpy(a, p, sizeof a);
if (a[sizeof a - 1] != ' ') {
// insufficient memory
// Maybe set last last character to the null character
a[sizeof a - 1] == ' ';
// 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] != ' ') {
....
更好的替代方案采用strlen(), strlcpy(), memcpy()
。 @Deduplicator。
在我的情况下,另请参阅strncpy或strlcpy。
对于标准的 C lib 单行代码,代码可以使用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();
strncpy()
实际上不是一个字符串函数;相反,它处理哪些零填充的非零字符序列,这些序列共同具有已知的固定长度。例如,它是填写数据结构的正确工具,这些数据结构随后被发送到其他程序、外部或持久化,以避免数据泄漏。
试图在其非常专业的利基市场之外使用它会导致可怕的扭曲和低效的代码。
有更合适的方法可以做到这一点,例如strlcpy()
和/或使用strlen()
和memcpy()
手动使用