strcpy 与 strdup

Posted

技术标签:

【中文标题】strcpy 与 strdup【英文标题】:strcpy vs strdup 【发布时间】:2012-12-10 19:39:06 【问题描述】:

我读到strcpy 用于复制字符串,strdup 返回指向新字符串的指针以复制字符串。

能否请您解释一下您更喜欢使用哪些情况strcpy,以及您更喜欢使用哪些情况strdup

【问题讨论】:

【参考方案1】:

strdup 为堆上的新字符串分配内存,而使用strcpy(或更安全的strncpy 变体)我可以将字符串复制到任一上的预分配内存堆或栈。

【讨论】:

为什么要强调“要么”?是不是不能用strcpy复制到静态缓冲区? 我试图强调这两个函数在使用上的差异,但不会因为太多的内存管理问题而使答案混乱。但是是的,您对静态缓冲区的看法是正确的。 如果你不想杂乱无章,你可以在“预分配内存”之后结束答案:-) small nitpick:strncpy 并不比 strcpy 安全,因为它不能保证 dest 会以空值终止。更糟糕的是,dest 缓冲区中任何未使用的空间都将被空终止符填充。此功能从未用于一般用途。如果必须使用这些函数之一,最好使用 strcpy 并手动终止 dest。【参考方案2】:

strcpy(ptr2, ptr1) 等价于while(*ptr2++ = *ptr1++)

strdup 等价于

ptr2 = malloc(strlen(ptr1)+1);
strcpy(ptr2,ptr1);

(memcpy version 可能更高效)

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

【讨论】:

除了最后一句话之外的好答案,这令人困惑。我猜你的意思是strdup()ed 字符串的生命周期可以超出当前函数的结尾,但无论如何都可能是这种情况(如果strcpy() 的目标是调用者提供的缓冲区、全局变量或本身使用malloc()new 手动分配)。 是的,如果调用者提供的缓冲区本身是一个全局变量或动态指针,那么就不需要使用 strdup 我刚刚指出了一个用例场景并感谢您完成它. 真的很喜欢while(*ptr2++ = *ptr1++)! :) 在while循环中,退出条件是如何工作的? @sbhatla 在 C 中,字符串以 nulbyte 结尾,计算结果为 false,赋值表达式计算为分配的值。【参考方案3】:

函数strcpystrncpy 是C 标准库的一部分,对现有内存进行操作。也就是说,you 必须提供函数将字符串数据复制到其中的内存,并且作为推论,you 必须有自己的方法来找出需要多少内存.

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

这使得strdup 成为“隐藏的malloc”便利函数之一,这可能也是它不属于标准库的原因。只要你使用标准库,你就知道你必须为每个malloc/calloc调用一个free。但是像strdup这样的函数引入了一个隐藏的malloc,为了内存管理,你必须把它和malloc一样对待。 (另一个这样的隐藏分配函数是 GCC 的abi::__cxa_demangle()。)小心!

【讨论】:

啊,我一直想知道为什么这不在 stdlib 中,现在我知道了。【参考方案4】:

char *strdup(char *pszSrch);

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

strdupd 失败时返回NULL。如果未分配内存,则复制失败strdup 返回NULL

【讨论】:

【参考方案5】:

在accepted answer中,strdup的实现表现为:

ptr2 = malloc(strlen(ptr1)+1);
strcpy(ptr2,ptr1);

但是,这有点不太理想,因为strlenstrcpy 都需要通过检查每个字符是否为\0 来查找字符串的长度。

使用memcpy应该更高效:

char *strdup(const char *src) 
    size_t len = strlen(src) + 1;
    char *s = malloc(len);
    if (s == NULL)
        return NULL;
    return (char *)memcpy(s, src, len);

【讨论】:

很好的答案,将strcpy 的概念使用与以有效方式实现strdup 的实用性区分开来。 鉴于 memcpy 依赖于知道字符串长度,无论哪种情况都会调用 strlen。 memcpy 本身等同于while ( len-- ) *ptr2++ = *ptr1++ ,它每次都会进行减法、赋值和测试为零,然后仍然必须运行一个赋值,然后是两个后增量和它们的赋值。所以这种 memcpy 技术似乎效率较低。这些似乎是微不足道的区别和想象中的优化。

以上是关于strcpy 与 strdup的主要内容,如果未能解决你的问题,请参考以下文章

strcpy 与 strdup

strcpy 与 memcpy

strcpy与strncpy

调用 strcpy 的结果与预期不同

(C)strcpy ,strncpy与strlcpy

字符数组拷贝与strcpy函数