我想要将src_str
复制到dst_arr
,应该使用什么方法?为什么?
char dst_arr[10];
char *src_str = "hello";
注意:我知道strlcpy
并非所有地方都可用,这不是问题所在。
PS:读了很多关于strncpy
和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()
更加安全,所以你最好使用它。
那些没有strlcpy()
的系统通常会有一个执行相同功能的s_strncpy()
。
注意:在指向某个东西之前,你不能将任何内容复制到dst_ptr
中。
strlcpy
时,你需要注意的唯一一件事就是,你应该为目标字符串提供(src_length + 1 for null)个字节的空间。正确吗? - harisrc_length + 1
,则在复制过程中不会丢失任何字符。也许您希望截断src,如果第三个参数小于src_length + 1
,则会发生这种情况。但是要小心,要将str截断为5个字符,第三个参数应该是6,并且dst大小必须至少为6,以避免缓冲区溢出。 - jfg956len
个字符的字符串(例如:"hello"的大小为5),您需要一个长度为len+1
个字符的缓冲区。 - jfg956strlcpy
的目的是避免输出缓冲区溢出。这意味着 size
参数是目标缓冲区的大小,而不是源缓冲区...确切地说,它是目标缓冲区中剩余的空间量。如果你"始终提供 src_length+1",你的代码将充满缓冲区溢出漏洞。 - Jim Balter在这种情况下,您应该始终使用标准函数,即C11的strcpy_s()
函数。不要使用strncpy()
,因为它不安全且不能保证零终止。也不要使用仅适用于OpenBSD的strlcpy()
,因为它也不安全,而且OpenBSD总是使用自己的发明,通常不会进入任何标准。
See 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
首先,您的dst_ptr没有分配空间,也没有设置它指向其他位置,因此将任何内容分配给它可能会导致段错误。
Strncpy应该可以正常工作 - 只需执行以下操作:
strncpy(dst_arr, src_str, sizeof(dst_arr));
你知道你不会溢出dst_arr。如果你使用更大的src_str,你可能需要在dst_arr的末尾放置自己的空终止符,但在这种情况下,你的源是<你的目标,所以它将被填充为null。
这在任何地方都有效且安全,所以除非出于学术好奇心,否则我不会考虑其他任何东西。
还要注意最好使用非魔术数字10,以便你知道其大小与strncpy的大小匹配 :)
strncpy
几乎从来都不是正确的选择,因为它会填充零值但不会添加零终止符。提问者想要使用strlcpy
,它会添加零终止符而不进行零填充。此外,谈论“在这种情况下”是一个错误,因为这个问题只是一个例子...真实的代码不会将一个固定的字符串(如"hello")复制到一个已知更大的固定大小缓冲区中。 - Jim Balter你不应该使用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必须是一个数组,而不是一个指针。
strlcpy
可以用于 OP 的需求。 - Jim Baltersizeof(int)
与sizeof(size_t)
不同时,sprintf(dst_arr,"%.*s",(sizeof dst_arr)-1,src_arr);
是未定义的行为。printf(dst_arr,"%.*s",(int) (sizeof dst_arr - 1),src_arr);
是朝着正确方向迈出的一步。 - chux - Reinstate Monica
strncpy
是一种转换函数,它将以零结尾的源字符串转换为非终止的固定宽度目标字符串。 - AnT stands with Russiachar dst_arr[10];
,它没有以空字符结尾。那么我应该使用strlcpy
对吗? - haridst_arr
最初是什么并不重要,它最初只是一块未初始化的原始内存块。问题是你想在dst_arr
中创建什么。我假设你想在dst_arr
中创建一个标准的普通零结尾字符串(因为你说你想将一个普通的零结尾字符串复制到它中)。如果是这样,请使用strlcpy
。如果你想在dst_arr
中创建一个“固定宽度字符串”(这相当不寻常,因为大多数时候现在没有人使用固定宽度字符串),请使用strncpy
。 - AnT stands with Russiastrncpy
不需要源字符串以 null 结尾。如果在 n 个字符中没有找到 null,则它会停止查找。但是,如果在前 n 个字符中找到 null,则将其视为终止符。与strlcpy
不同,后者总是需要在s
的末尾找到 null,以便可以返回strlen(s)
。 - greggo