strdup() - 它在C中做了什么?

时间:2008-10-31 07:15:46

标签: c function strdup

C中strdup()函数的用途是什么?

10 个答案:

答案 0 :(得分:351)

听起来完全是这样,假设你已经习惯了C和UNIX分配单词的缩写方式, 重复字符串 : - )

请记住,它实际上不是ISO C标准本身的一部分(a)(它是POSIX的东西),它实际上与下面的代码一样:

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

换句话说:

  1. 它尝试分配足够的内存来保存旧字符串(加上'\ 0'字符来标记字符串的结尾)。

  2. 如果分配失败,则会将errno设置为ENOMEM并立即返回NULLerrnoENOMEM的设置是malloc在POSIX中的作用,因此我们无需在strdup中明确执行此操作。如果您 POSIX兼容,ISO C实际上并不强制要求存在ENOMEM,所以我没有在此处包含(b)。< / p>

  3. 否则分配工作,所以我们将旧字符串复制到新字符串(c)并返回新地址(调用者负责在某些时候释放)。

  4. 请记住,这是概念性的定义。任何值得他们工资的图书馆作家都可能提供针对所使用的特定处理器的大量优化代码。


    (a)但是,标准为未来方向保留以str开头的小写字母和小写字母。来自C11 7.1.3 Reserved identifiers

      

    每个标头声明或定义其关联子条款中列出的所有标识符,并且*可选地声明或定义其关联的未来库方向子条款中列出的标识符。**

    string.h的未来路线可在C11 7.31.13 String handling <string.h>中找到:

      

    strmemwcs开头的函数名称和小写字母可以添加到<string.h>标题中的声明中。

    如果你想要安全的话,你应该把它叫做别的东西。


    (b)这一变化基本上是用以下代替if (d == NULL) return NULL;

    if (d == NULL) {
        errno = ENOMEM;
        return NULL;
    }
    

    (c)请注意,我使用strcpy,因为这清楚地表明了意图。在一些实现中,使用memcpy可能更快(因为您已经知道长度),因为它们可以允许以更大的块或并行地传输数据。或者它可能不会:-)优化口头禅#1:“测量,不要猜测”。

    无论如何,如果你决定走这条路,你会做类似的事情:

    char *strdup(const char *src) {
        size_t len = strlen(src) + 1;       // String plus '\0'
        char *dst = malloc(len);            // Allocate space
        if (dst == NULL) return NULL;       // No memory
        memcpy (dst, src, len);             // Copy the block
        return dst;                         // Return the new string
    }
    

答案 1 :(得分:83)

char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

可能代码比使用strcpy()快一点,因为\0字符不需要再次搜索(它已经与strlen())。

答案 2 :(得分:50)

没有必要重复其他答案,但请注意strdup()可以从C角度做任何想做的事情,因为它不是任何C标准的一部分。但它由POSIX.1-2001定义。

答案 3 :(得分:17)

来自strdup man

strdup()函数应返回指向新字符串的指针,该字符串是s1指向的字符串的副本。返回的指针可以传递给free()。如果无法创建新字符串,则返回空指针。

答案 4 :(得分:4)

strdup()为包含结束字符'\ 0'的字符数组进行动态内存分配,并返回堆内存的地址:

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

所以,它的作用是给我们另一个与其参数给出的字符串相同的字符串,而不需要我们分配内存。但我们以后仍然需要释放它。

答案 5 :(得分:3)

它通过运行传入的字符串的 malloc strcpy 来传递传入的字符串的副本。将malloc的缓冲区返回给调用者,因此需要在返回值上运行 free

答案 6 :(得分:3)

strdupstrndup在POSIX兼容系统中定义为:

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

strdup()函数为该副本分配足够的内存 字符串str,复制,并返回指向它的指针。

指针随后可以用作函数free的参数。

如果内存不足,则返回NULL并将errno设置为 ENOMEM

strndup()函数从字符串len复制最多str个字符,始终为null,终止复制的字符串。

答案 7 :(得分:1)

它最有价值的是给你另一个与第一个相同的字符串,而不需要你自己分配内存(位置和大小)。但是,如上所述,您仍然需要释放它(但也不需要数量计算。)

答案 8 :(得分:1)

声明:

strcpy(ptr2, ptr1);

等同于(除了改变指针的事实):

while(*ptr2++ = *ptr1++);

鉴于:

ptr2 = strdup(ptr1);

相当于:

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

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

答案 9 :(得分:0)

strdup()函数是字符串重复的简写,它接受一个参数作为字符串常量或字符串文字,并为字符串分配足够的空间,并在分配的空间中写入相应的字符,最后返回地址调用例程的已分配空间。