strcpy与strdup


74

我读到的strcpy是复制字符串,并strdup返回一个指向新字符串的指针以复制该字符串。

您能否解释一下您喜欢使用strcpy哪种情况以及您喜欢使用哪种情况strdup

Answers:


106

strcpy(ptr2, ptr1) 相当于 while(*ptr2++ = *ptr1++)

其中strdup等于

memcpy版本可能更有效)

因此,如果希望复制的字符串在另一个函数中使用(因为它是在堆部分中创建的),则可以使用strdup,否则使用strcpy就足够了。


6
除了最后一句话,答案很好,这很令人困惑。我想你的意思是strdup()ed字符串的生命周期可以延长到当前函数的末尾,但是无论如何都是这样(如果目标strcpy()是调用方提供的缓冲区,全局变量,或者使用malloc()或手动分配的本身new) 。
j_random_hacker 2012年

1
是的,的确如此,如果调用者提供的缓冲区本身是全局变量或动态指针,则无需使用strdup,我只是指出了一种用例场景,并感谢您完成此操作。
Abdul Muheedh

9
真爱while(*ptr2++ = *ptr1++)!:)
Aloys

1
在while循环中,退出条件如何工作?
sbhatla

3
@sbhatla在C字符串中以nul结尾,其结果为false,赋值表达式的结果为赋值。

56

函数strcpystrncpy是C标准库的一部分,并在现有内存上运行。也就是说,必须提供到其中的功能复制字符串数据的存储,并作为一个必然结果,必须有自己的找出你需要多少内存的方式。

相比之下,strdup它是Posix函数,它为您执行动态内存分配。它返回一个指向新分配的内存的指针,该内存已将字符串复制到该内存中。但是现在必须对此内存负责,并且最终必须对此负责free

这使它strdup成为“隐藏的malloc”便利功能之一,并且大概也是为什么它不属于标准库的原因。只要您使用标准库,就知道您必须freemalloc/调用一个calloc。但是,strdup引入诸如hidden的功能malloc,就malloc内存管理而言,必须将其与视为相同。(另一个隐藏的分配功能是GCC的abi::__cxa_demangle()。)当心!


1
啊,我一直想知道为什么它不在stdlib中,现在我知道了。
莫里·马克维兹

14

strdup分配存储器,用于在堆上新的字符串,同时使用strcpy(或它的更安全strncpy的变体光盘),我可以一个字符串复制到一个预先分配的存储器上或者堆或堆。


1
为什么强调“两者皆是”?不能使用strcpy复制到静态缓冲区吗?
Kerrek SB 2012年

我试图强调两个函数在用法上的差异,而不会因过多的内存管理问题而使答案混乱。但是是的,您对静态缓冲区是正确的。
Oren 2012年

如果您不想混乱,可以在“预分配的内存”之后结束答案:-)
Kerrek SB 2012年

小型nitpick:strncpy并不比strcpy更安全,因为它不能保证dest将以null终止。更糟糕的是,dest缓冲区中任何未使用的空间都将填充空终止符。此功能从不用于一般用途。如果必须使用这些功能之一,则最好使用strcpy并手动终止dest。
JohnF

11

接受的答案中,的实现strdup表示为:

然而,有些次优的,因为两者strlenstrcpy需要通过检查每个字符是一个查找的字符串的长度\0

使用memcpy应该更有效:


1
好的答案将实现的概念使用与strcpy有效实现strdup的实用性区分开来。
Michael Gaskill 2016年

鉴于memcpy取决于知道的字符串长度,在两种情况下都将调用strlen。memcpy本身等效于while ( len-- ) { *ptr2++ = *ptr1++ },每次执行一次减法,赋值并测试零,然后仍然必须运行一个赋值,然后再执行两个后期增量及其赋值。因此,这种memcpy技术似乎效率较低。这些似乎是微不足道的区别和虚构的优化。

0

char *strdup(char *pszSrch);

strdup将分配存储区原始字符串的大小。如果存储分配成功,则将原始字符串复制到重复的字符串。

strdupdNULL失败返回。如果未分配内存,则复制失败strdupreturn NULL

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.