当我想将src_str
复制到dst_arr
时,我应该使用什么,为什么?
char dst_arr[10];
char *src_str = "hello";
PS:读了很多关于好或坏是strncpy
和strlcpy
的文章后,我的头转得比我电脑的磁盘还快。
注意:我知道strlcpy
不是无处不在。这不是我们所关心的。
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
成为正确的函数使用。
strlcpy()
比strncpy()
更安全,所以你不妨使用它。
没有它的系统通常会有一个s_strncpy()
做同样的事情。
注意:你不能复制任何东西到dst_ptr
,直到它指向的东西
我不知道strlcpy。我刚刚在这里发现:
strlcpy()和strlcat()函数复制和连接字符串分别。它们被设计得更安全,更一致,而且strncpy(3)和strncat(3)的更少的错误替换。
更安全。
编辑:这里有完整的讨论。
Edit2 :
我意识到我上面写的并没有回答你问题中"在你的情况下"的部分。如果你了解 strncpy的局限性,我想你可以使用它并围绕它编写好的代码来避免它的陷阱;但是如果你不确定你对它的限制的理解,请使用strlcpy。我对strncpy和strlcpy局限性的理解是,你可以用strncpy(缓冲区溢出)做一些非常糟糕的事情,最糟糕的是你可以用strlcpy在进程中丢失一个字符。
您应该始终使用标准函数,在本例中是C11 strcpy_s()
函数。不是strncpy()
,因为这是不安全的,不能保证零终止。而不是仅OpenBSD的strlcpy()
,因为它也不安全,而且OpenBSD总是提出自己的发明,通常不会使其成为任何标准。
看到http://en.cppreference.com/w/c/string/byte/strcpy
函数strcpy_s类似于BSD函数strlcpy,不同的是Strlcpy截断源字符串以适应目标(这是一个安全风险)
- strlcpy不执行strcpy_s所做的所有运行时检查
- strlcpy通过将目标设置为空字符串或在调用失败时调用处理程序来避免明显的失败。
- 尽管strcpy_s由于潜在的安全风险而禁止截断,但可以使用边界检查的strncpy_s来截断字符串。
如果您的C库没有strcpy_s
,请使用safe库。https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html
首先,您的dst_ptr没有分配空间,并且您没有将其设置为指向其他空间,因此向其分配任何内容可能会导致分割错误。
Strncpy应该可以很好地工作-只需执行:
strncpy(dst_arr, src_str, sizeof(dst_arr));
,你知道你不会溢出dst_arr。如果您使用更大的src_str,则可能需要在dst_arr的末尾放置自己的空终止符,但在本例中,您的源是<你的dest,所以无论如何它都会被空填充。>
这在任何地方都有效,而且很安全,所以我不会看其他任何东西,除非它的求知欲。
还要注意的是,最好使用非幻数表示10,这样你就知道它的大小与strncpy的大小相匹配:)
不应该使用strncpy和not 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必须是数组而不是指针