什么时候使用strdup(与malloc / strcpy相比)是一个好主意?



可以用mallocstrcpy代替吗?哪个更好?

例如:

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()将复制所有内容。但是如果你只是想要你的文本的一部分,你应该使用这些说明。

相关内容

最新更新