Strncpy只能与固定长度的数组一起使用



根据此StackOverflow注释,strncpy不应与非固定长度数组一起使用。

strncpy永远不应该使用,除非您在处理结构/二进制文件中的固定宽度(不一定是终止的字符串字段)。–R..一月11'12在16:22

我知道,如果您为字符串动态分配内存,这是多余的,但是否有理由使用strncpy而不是strcpy

strncpy会将数据复制到您指定的限制,但如果它在字符串结束前达到该限制,则会使目标未终止

换句话说,strncpy有两种可能性。一种是,您得到的行为与strcpy无论如何都会产生的行为完全一样(除了速度较慢,因为它用NUL填充了目标缓冲区的剩余部分,而实际上您从来都不想要或关心NUL)。另一个是,它产生了一个你通常无法真正使用的结果。

如果您想将最大长度的字符串复制到固定长度的缓冲区中,您可以(例如)使用sprintf来完成以下工作:

char buffer[256];
sprintf(buffer, "%255s", source);

strncpy不同,这个总是零终止结果,因此结果总是可用作字符串。

如果你不想使用sprintf(或类似的),我建议你只写一个真正做你想做的事情的函数,按照这个一般顺序:

void copy_string(char const *dest, char const *source, size_t max_len) { 
size_t i;
for (i=0; i<max_len-1 && source[i]; i++)
dest[i] = source[i];
dest[i] = '';
}

由于您已经将其标记为C++(除了C之外):我的建议是通常通过使用std::string来避免C++中的整个混乱。

如果你真的必须在C++中使用NUL终止的序列,你可能会考虑另一种可能性:

template <size_t N>
void copy_string(char const (&dest)[N], char const *source) {
size_t i;
for (i=0; i<N-1 && source[i]; i++)
dest[i] = source[i];
dest[i] = '';
}

只有当目标是实际数组(而不是指针)时,这才有效,但在这种情况下,它会让编译器推断数组的大小,而不需要用户显式传递。这通常会使代码更快一点(减少函数调用的开销),更难搞砸和传递错误的大小。

反对使用strncpy的论点是,它不能保证字符串以null结尾。

当使用非固定长度数组时,在C中复制字符串的不太容易出错的方法是使用snprintf,它可以确保字符串的null终止。

一篇很好的博客文章,评论*n*的功能。

这些函数允许您指定缓冲区的大小,但这一点非常重要,它们不能保证null终止。如果您要求这些函数写入比填充缓冲区更多的字符,那么它们将停止,从而避免缓冲区溢出,但它们不会null终止缓冲区。

这意味着在不处理固定数组时使用strncpy和其他此类函数会带来非空终止字符串的不必要风险,这些字符串可能会成为代码中的定时炸弹。

char*strncpy(char*目的地,const char*源,size_t num)

strncpy()的限制:

  1. 如果目标字符串已完全填充,则不会在其上放置null终止符。并且,如果source比num.长,则不会在destination的末尾隐式附加null字符
  2. 如果num大于源字符串的长度,则目标字符串将填充长度不超过num的空字符

与strcpy一样,它不是内存安全操作。因为它在复制源之前并没有检查目标中是否有足够的空间,所以这是导致缓冲区溢出的潜在原因。

参考:为什么要使用strncpy而不是strcpy?

我们有两个版本可以将字符串从一个复制到另一个1> strcpy2> strncpy这两个版本用于固定长度数组和非固定长度数组。strcpy在复制字符串时不检查目标字符串的上限,strncpy会检查它。当目标字符串达到这个上限时,函数strncpy将返回错误代码,同时函数strcpy会在当前进程的内存中造成一些影响,并立即终止进程。因此strncpy比strcpy 更安全

相关内容

  • 没有找到相关文章

最新更新