我可以使用malloc
和strcpy
来替换它吗?哪个更好?
例如:
char *s = "Global View";
char *d;
d = strdup(s);
free(d);
或者
char *s = "Global View";
char *d = malloc(strlen(s) +1);
strcpy(d,s);
free(d);
我可以使用malloc
和strcpy
来替换它吗?哪个更好?
例如:
char *s = "Global View";
char *d;
d = strdup(s);
free(d);
char *s = "Global View";
char *d = malloc(strlen(s) +1);
strcpy(d,s);
free(d);
哪个更好?
strdup(s);
本身在分配失败时不会产生问题(调用代码仍需要处理NULL
返回),不像下面的是未定义行为或UB。
char *d = malloc(strlen(s) +1);
strcpy(d,s); // should not be called if `d == NULL`.
< p > < code > strdup(s) 的典型实现不像替代方案那样两次遍历< code > s 的长度。
// 1st pass to find length of `s`
char *d = malloc(strlen(s) +1);
// Weak compiler/library may run 2nd pass to find length of `s` and then copy
strcpy(d,s);
strdup(s)
函数会在长度需要时使用最佳复制代码进行一次遍历。可能是通过使用 memcpy()
或等效函数实现的。strdup()
预计经常使用,实现这个非标准 C 库函数的库应该被设计成能够最优化地执行。当有最好的工具可用时,请使用它。以下是一个示例实现:#include <errno.h>
#include <stdlib.h>
char *my_strdup(const char *s) {
if (s == NULL) { // Optional test, s should point to a string
#ifdef EINVAL
errno = EINVAL; // For systems that support this "invalid argument" errno
#endif
return NULL;
}
size_t siz = strlen(s) + 1;
char *y = malloc(siz);
if (y != NULL) {
memcpy(y, s, siz);
} else {
#ifdef ENOMEM
errno = ENOMEM; // For systems that support this "out-of-memory" errno
#else
;
#endif
}
return y;
}
strdup()
与保留名称空间@Jonathan Leffler @Joshua 冲突。
malloc()/memcpy()/strcpy()
的一个重要优点是它们是标准的C库函数。虽然strdup()
非常普遍,但它不在标准C库中。strdup()
可能会出现在C2x中: Add strdup and strndup to C2X?strdup()
。它只是在§7.31.13字符串处理<string.h>
中定义了未来库方向。_以小写字母开头的函数名,如str
、mem
或wcs
,可以添加到<string.h>
头文件的声明中。_这是一个笼统的规定,当然包括strdup()
,但并没有将其从所有与模式str[a-z].*
匹配的函数名中单独挑出来。 - Jonathan Lefflerstrdup()
本身在内存分配失败时不会导致未定义的行为。d = strdup(s); free(d);
是可以的,无论是否出现内存不足的情况。在这个简单的例子中不需要检查。当分配失败时,OP的代码char *d = malloc(strlen(s) +1); strcpy(d,s);
是UB。正如你所评论的那样,下面的代码如何使用strdup()
的返回值非常重要。健壮的代码通常应该检查其返回值。 - chux - Reinstate Monicastrdup()
和strndup()
作为系统库的一部分可用? - Dúthomhasstrdup()
函数。这是你在SO上发布的一个有趣问题。我也不会感到惊讶,如果在嵌入式编译器中根本找不到strdup()
函数。 - chux - Reinstate Monica除了strdup更简短之外,没有太大的区别。
strdup == malloc + strcpy
strcpy
之前应该真正检查 malloc
返回的结果。在使用 strdup
版本时,应该检查最终结果是否为NULL。 - BaseZenstrdup()
可以在使用libc字符串处理函数时保持一致。 strdup()
意味着操作数是libc的模型,即以空字符结尾的字符串。
libc的str...()
函数完美地解决了C字符串处理的基本问题,因此只要它们足够使用,就应该使用它们,即使出于其他原因,也要让您的代码更容易被他人理解,并避免编写不必要的代码。NULL
表示文字值'\0'
很诱人。大多数C程序员知道所有形式的NULL
都可以工作。在相关场景中使用'\0'
的优点是,它是一种简洁的方式来澄清您的意图。 '\0'
代表一个字符,仅此而已。我建议尽量使用strdup()函数。而malloc() + memcpy()只在字符串很大且你知道实际大小的情况下使用。这样可以节省计算字符串长度所需的时间。由于这是一个非常快速的函数,你只能在几兆字节的文本上才能感受到差异。 假设你有一个struct string结构体
typedef struct string
{
char* st;
long buf;
long n;
} String;
char * stringdup(String *st)
{
char *res=malloc(st->n);
res?memcpy(res,st->st,st->n):NULL;
}
memcpy(res,st->st,1)
,为什么只复制一个字符到 res
中?不清楚代码为什么使用 long
类型来表示字符串的大小。建议改用 size_t
。 - chux - Reinstate Monica*res = *(st->st)
- 更快的代码 - 没有库调用。 - clearlight
strdup
不是ISO C的一部分。 - M.Mstrdup
。自行实现该功能很简单,而且没有理由怀疑库的实现会更加高效,因为优化在于strlen
和memcpy
。 - Lundinstrdup
至少已经成为 POSIX 标准12年。 - Andrew Henle