当我想将src_str
复制到dst_arr
时,我应该使用什么?为什么?
char dst_arr[10];
char *src_str = "hello";
PS:在阅读了很多关于好 1>} strncpy
和{{}的内容之后,我的头比我的电脑磁盘旋转得更快1}}。
注意:我知道strlcpy
无处不在。这不是问题。
答案 0 :(得分:28)
strncpy
永远不会正确答案。 strncpy
是一个旨在与非终止固定宽度字符串一起使用的函数。更准确地说,其目的是将以零结尾的字符串转换为非终止的固定宽度字符串(通过复制)。换句话说,strncpy
在这里没有任何意义。
您在这里的真正选择是在strlcpy
和普通strcpy
之间。
如果要执行“安全”(即可能被截断)复制到dst_arr
,正确使用的功能是strlcpy
。
至于dst_ptr
......没有“复制到dst_ptr
”之类的东西。您可以复制到dst_ptr
指向的内存,但首先必须确保它指向某处并分配该内存。有很多不同的方法可以做到这一点。
例如,您只需将dst_ptr
指向dst_arr
,在这种情况下,答案与上一个案例中的答案相同 - strlcpy
。
或者您可以使用malloc
分配内存。如果分配的内存量足以保证字符串的足够(即分配了至少strlen(src_str) + 1
个字节),那么您可以使用普通strcpy
甚至memcpy
来复制串。在这种情况下,没有必要也没有理由使用strlcpy
,尽管有些人可能更喜欢使用它,因为它以某种方式让他们感到更加安全。
如果你故意分配更少的内存(即你希望你的字符串被截断),那么strlcpy
将成为正确使用的函数。
答案 1 :(得分:5)
strlcpy()
比strncpy()
更安全,所以你不妨使用它
没有它的系统通常会有s_strncpy()
做同样的事情。
注意:在指向某事之前,您无法将任何内容复制到dst_ptr
答案 2 :(得分:2)
我不知道strlcpy。我刚刚找到了here:
strlcpy()和strlcat()函数复制和连接字符串 分别。它们旨在更安全,更一致,更安全 strncpy(3)和strncat(3)的更容易出错的替换。
因此接缝更加安全。
修改:可以进行完整的讨论here。
<强> EDIT2 强>:
我意识到我上面写的内容并没有回答你问题的“在你的情况下”部分。如果您理解 strncpy的限制,我想您可以使用它并在其周围编写好的代码以避免其陷阱;但如果您不确定自己对其限制的理解,请使用strlcpy。
我对strncpy和strlcpy的局限性的理解是你可以用strncpy(缓冲区溢出)做一些非常糟糕的事情,而你用strlcpy做的最糟糕的事情就是在这个过程中松掉一个char。
答案 3 :(得分:1)
您应始终使用标准函数,在本例中为C11 strcpy_s()
函数。不是strncpy()
,因为这不安全,不能保证零终止。而不仅仅是OpenBSD strlcpy()
,因为它也是不安全的,OpenBSD总是提出它自己的发明,它们通常不会成为任何标准。
请参阅 http://en.cppreference.com/w/c/string/byte/strcpy
函数strcpy_s类似于BSD函数strlcpy,除了 strlcpy截断源字符串以适应目标(这是一个安全风险)
如果您的C库没有strcpy_s
,请使用safec lib。
https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html
答案 4 :(得分:-1)
首先,您的dst_ptr没有分配空间,并且您没有将其设置为指向其他空间,因此为此分配任何内容都可能导致分段错误。
Strncpy应该可以正常工作 - 只需:
strncpy(dst_arr, src_str, sizeof(dst_arr));
你知道你不会溢出dst_arr。如果你使用更大的src_str,你可能必须在dst_arr的末尾放置你自己的null-terminator,但是在这种情况下你的源是&lt;你的目标,所以无论如何都会用空值填充。
这在任何地方都可以使用并且安全,所以除非知识分子的好奇,否则我不会看其他任何东西。
另请注意,为10使用非魔术数字会很好,所以你知道它的大小与strncpy的大小匹配:)
答案 5 :(得分:-1)
你不应该使用strncpy而不是strlcpy。更好的使用
*dst_arr=0; strncat(dst_arr,src_arr,(sizeof dst_arr)-1);
或没有初始化
sprintf(dst_arr,"%.*s",(sizeof dst_arr)-1,src_arr);
dst_arr这里必须是一个数组而不是一个指针。