可以用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`.
strdup(s)
的典型实现不会像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库中,尽管它非常常用实现。
[edit] strdup()
可能在C2x:添加strdup和strndup到C2x ?
除了strdup被缩短了之外,没有太大的区别。Strdup == malloc + strcpy
在使用libc字符串处理函数时使用strdup()
是一致的。strdup()
暗示操作数是libc的以空结束的字符串模型。
libc的str...()
函数完美地解决了C字符串处理的基本问题,所以只要它们足够,就使用它们,如果没有其他原因,就是为了使您的代码更快地被其他人理解,并避免编写不必要的代码。
如果没有令人信服的理由,我个人不会混合模型。可能会出现用自定义函数补充libc字符串函数很有帮助或有必要的情况,或者可能完全绕过它们,例如,并非所有C平台都提供libc。也许有链接问题,或者你在内核上下文中工作,无法在没有崩溃或大量努力的情况下访问libc,等等…
可以使用0或NULL
来表示文字值' '
。大多数C程序员都知道所有形式的NULL
都可以工作。在相关的地方使用' '
的好处是,它是一种消除歧义的简洁方式意图。' '
表示字符,没有其他字符。
我建议使用strdup()。malloc() + memcpy()只适用于大长度的字符串,您知道实际长度。这使您可以节省记录字符串以获得长度的时间。由于这是一个非常快的函数,因此您只能在几兆字节的文本中感受到差异。假设你有一个struct string
typedef struct string
{
char* st;
long buf;
long n;
} String;
在这种情况下,你可以获得字符串的实际大小,所以如果我应该strdup()这个字符串,我会写:
char * stringdup(String *st)
{
char *res=malloc(st->n);
res?memcpy(res,st->st,st->n):NULL;
}
你可以注意到:当我复制字符串时,我返回一个char *而不是string。经验告诉我们,struct string很适合用于构建字符串,但不适合用于存储字符串。因为所有调试器都可以将char*显示为字符串,但没有人会知道你的结构。所以一旦你定义了最终字符串,最好离开这个结构体。您节省了空间,并且调试速度更快。这也是解释的原因,因为对于小文本,不值得使用这样的说明。你永远不会欣赏它,但它会弄乱你的代码。
<标题>更新:我忘了另一种情况。当您只需要复制字符串的一个子集时,可以使用malloc() + memcpy()。Strdup()和strcpy()将复制所有内容。但是如果你只是想要你的文本的一部分,你应该使用这些说明。
标题>