23

当我想复制src_str到时我应该使用什么dst_arr,为什么?

char dst_arr[10];
char *src_str = "hello";

PS:读了很多关于好坏的东西后,我的头比我的电脑磁盘旋转更快。strncpystrlcpy

注意:我知道strlcpy并非随处可用。这不是这里的问题。

4

6 回答 6

36

strncpy当您的目标字符串以零结尾时,它永远不是正确答案。strncpy是一个旨在与非终止的固定宽度字符串一起使用的函数。更准确地说,它的目的是将零终止的字符串转换为非终止的固定宽度字符串(通过复制)。换句话说,strncpy在这里没有意义。

您在这里真正的选择是 betweenstrlcpy和 plain strcpy

当您想要执行“安全”(即可能被截断)复制到dst_arr时,要使用的正确函数是strlcpy.

至于dst_ptr......没有“复制到dst_ptr”这样的东西。您可以复制到指向的内存dst_ptr,但首先您必须确保它指向某处并分配该内存。有很多不同的方法可以做到这一点。

例如,您可以只dst_ptr指向dst_arr,在这种情况下,答案与前一种情况相同 - strlcpy

或者您可以使用malloc. 如果您分配的内存量保证足够用于字符串(即至少strlen(src_str) + 1分配了字节),那么您可以使用普通strcpy甚至memcpy复制字符串。在这种情况下没有必要也没有理由使用strlcpy它,尽管有些人可能更喜欢使用它,因为它以某种方式给了他们额外的安全感。

如果您有意分配更少的内存(即您希望您的字符串被截断),那么strlcpy就成为正确的函数。

于 2011-08-08T19:07:21.770 回答
6

strlcpy()strncpy()你还不如使用它更安全。
没有它的系统通常会有一个s_strncpy()做同样事情的系统。

注意:你不能复制任何东西,dst_ptr直到它指向某个东西

于 2011-08-08T19:06:55.400 回答
2

我不知道strlcpy。我刚刚在这里发现:

strlcpy() 和 strlcat() 函数分别复制和连接字符串。它们被设计为更安全、更一致且更不易出错的 strncpy(3) 和 strncat(3) 替代品。

所以 strlcpy 接缝更安全。

编辑:这里有完整的讨论。

编辑2

我意识到我上面写的内容并没有回答您问题的“在您的情况下”部分。如果您了解strncpy 的局限性,我想您可以使用它并围绕它编写好的代码来避免它的陷阱;但如果您不确定自己对它的限制的理解,请使用 strlcpy。

我对 strncpy 和 strlcpy 的局限性的理解是,你可以用 strncpy 做一些非常糟糕的事情(缓冲区溢出),而你可以用 strlcpy 做的最糟糕的事情就是在这个过程中丢失一个字符。

于 2011-08-08T19:09:29.733 回答
1

您应该始终使用标准函数,在本例中为 C11strcpy_s()函数。不strncpy(),因为不保证零终止是不安全的。而不是 OpenBSD-only 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,请使用 safec 库。 https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html

于 2017-11-16T00:35:30.980 回答
-1

首先,您的 dst_ptr 没有分配空间,并且您没有将其设置为指向其他空间,因此分配任何内容可能会导致分段错误。

Strncpy 应该可以正常工作 - 只需执行以下操作:

strncpy(dst_arr, src_str, sizeof(dst_arr));

你知道你不会溢出 dst_arr。如果您使用更大的 src_str,您可能必须在 dst_arr 的末尾放置您自己的空终止符,但在这种情况下,您的源是 < 您的目标,因此无论如何都会用空值填充它。

这在任何地方都有效并且很安全,所以我不会看其他任何东西,除非它的智力好奇心。

另请注意,最好对 10 使用非幻数,这样您就知道它的大小与 strncpy 的大小匹配:)

于 2011-08-08T19:11:19.307 回答
-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 必须是数组而不是指针。

于 2011-08-08T20:17:20.983 回答