根据this StackOverflow注释strncpy
不应该与非固定长度数组一起使用。
除非您使用结构/二进制文件中的固定宽度,不一定终止的字符串字段,否则永远不应使用
strncpy
。 - R .. 2012年1月11日16:22
我知道如果你为字符串动态分配内存是多余的,但有理由说使用strncpy
而不是strcpy
答案 0 :(得分:3)
strncpy
会将数据复制到您指定的限制 - 但如果它在字符串结尾之前达到该限制,则会离开目标未终结。< / p>
换句话说,strncpy
有两种可能性。一个是你得到的行为与strcpy
无论如何都会产生(除了更慢,因为它用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] = '\0';
}
因为你已经将它标记为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] = '\0';
}
这仅在目标是实际数组(而不是指针)时才有效,但在这种情况下,它会让编译器推断出数组的大小,而不是要求用户明确地传递它。这通常会使代码更快一点(函数调用中的开销更少),并且更难以搞砸并传递错误的大小。
答案 1 :(得分:2)
反对使用strncpy
的论点是它不保证你的字符串将被终止。
使用非固定长度数组时,在C中复制字符串的错误较少的方法是使用snprintf
来保证字符串的空终止。
好Blog Post评论*n*
个功能。
这些函数允许您指定缓冲区的大小但是 - 这非常重要 - 它们不保证空终止。如果你要求这些函数写入比填充缓冲区更多的字符,那么它们将停止 - 从而避免缓冲区溢出 - 但它们不会使终止缓冲区。
这意味着在不处理固定数组时使用strncpy
和其他此类函数会引入非空终止字符串的风险,这可能是代码中的定时炸弹。
答案 2 :(得分:0)
char * strncpy(char * destination,const char * source,size_t num);
strncpy()的限制:
与strcpy一样,它不是一个内存安全的操作。因为它在复制源之前没有在目标中检查足够的空间,所以它可能是缓冲区溢出的原因。
答案 3 :(得分:-1)
我们有2个版本的复制字符串从一个到另一个 1 GT;的strcpy 2 - ;函数strncpy 这两个版本用于固定和非固定长度数组。 strcpy在复制字符串时不检查目标字符串的上限,strncpy会检查它。当目标字符串到达此上限时,函数strncpy将返回错误代码,同时函数strcpy将在当前进程的内存中产生一些影响并立即终止进程。因此strncpy比strcpy更安全