';memdup';C语言中的函数?

';memdup';C语言中的函数?,c,memcpy,strdup,C,Memcpy,Strdup,在C语言中,您可以使用strdup简洁地分配缓冲区并将字符串复制到其中。然而,据我所知,一般记忆没有类似的功能。例如,我不能说 struct myStruct*foo=malloc(sizeof(struct myStruct)); 填写我的结构(foo); struct myStruct*bar=memdup(foo,sizeof(struct myStruct)); //bar现在是一个新的、大小合适的内存块的引用, //其内容与foo的内容相同 那么,我的问题有三个: 有没有像这样的标准

在C语言中,您可以使用
strdup
简洁地分配缓冲区并将字符串复制到其中。然而,据我所知,一般记忆没有类似的功能。例如,我不能说

struct myStruct*foo=malloc(sizeof(struct myStruct));
填写我的结构(foo);
struct myStruct*bar=memdup(foo,sizeof(struct myStruct));
//bar现在是一个新的、大小合适的内存块的引用,
//其内容与foo的内容相同
那么,我的问题有三个:

  • 有没有像这样的标准库函数我不知道
  • 如果没有,是否有一种简洁且最好是标准的方法来做到这一点,而无需显式调用
    malloc
    memcpy
  • 为什么C包含
    strdup
    而不包含
    memdup

  • 复制任意内存结构并不像复制字符串那样简单。例如,当结构包含指向其他结构(如字符串)的指针时,应该如何处理?“复制”这样的结构意味着什么?与string的情况不同,没有一个正确的答案。在这种情况下,最好让应用程序开发人员根据他们的用例创建一种复制结构的机制,而不是假装有一种规范的方法来处理它,从而混淆问题。

    strdup函数在以null结尾的字符串上读取并复制null。但是,普通数据没有任何此类分隔符,因此您需要为其指定要复制的数据长度。

    您可以通过一个简单的函数来实现它:

    void* memdup(const void* mem, size_t size) { 
       void* out = malloc(size);
    
       if(out != NULL)
           memcpy(out, mem, size);
    
       return out;
    }
    

    您可能只想自己定义
    memdup()
    ,然后按照前面的建议在代码中使用它。我的函数版本如下

    void *memdup(const void *src, size_t n)
    {
        void *dest;
    
        dest = malloc(n);
        if (dest == NULL)
                return NULL;
    
        return memcpy(dest, src, n);
    }
    
    至于讨论
    memdup()
    是否太琐碎甚至多余,我不这么认为。它对于在代码中复制结构非常有用。C标准库的ANSI/ISO和POSIX标准都包含许多方便的函数,但不幸的是,这不是一个

    示例:使用
    memdup()
    重新实现
    strdup()

    示例:使用
    memdup()
    复制对象

    int some_function(const struct some_struct *some_const_data)
    {
        struct some_struct *my_mutable_copy;
    
        my_mutable_copy = memdup(some_const_data, sizeof *some_const_data);
        if (my_mutable_copy == NULL)
            return -1;
    
        ...
    
        return 0;
    }
    

    GNU Gnulib的
    xalloc.h
    中有
    void*xmemdup(void const*p,size\t s)


    请注意,如果内存不足,它会调用
    xalloc\u die

    不会
    strdup
    只是一个
    malloc
    和一个
    memcpy
    ?这是两个函数调用。(
    malloc()
    memcpy()
    )似乎太琐碎了,不值得为其创建函数<如果您想避免对字符串进行过多的传递,则代码>strdup()会稍微复杂一些。@Mystical:strdup()的哪个实现不需要对输入字符串进行两次传递?(一次调整缓冲区大小,一次复制)我的目的主要是为了代码可读性——我想从
    struct myStruct*bar=(struct myStruct*)malloc(sizeof(struct myStruct));memcpy(bar、foo、sizeof(struct-myStruct))到一个相对较短的行,在那里可以清楚地看到发生了什么。@Dan不要抛出
    malloc
    的结果。”。除此之外,C不包括
    strdup
    。不过,POSIX确实如此,所以它的应用非常广泛。但你不能指望它是可用的。和
    struct myStruct*bar=malloc(sizeof*bar)*bar=*foo看起来还不错,是吗?有memcpy(),memcmp(),memmemmem(),memchr()。正如前面所指出的,
    void*memdup(const void*mem,size\u t size)
    ?与memcpy()的工作方式相同。它的意思是复制一个内存区域,这个内存区域碰巧是一个数据结构。除非memdup不是结构的副本。根据名称,它将复制一个内存区域。这是memdup,不是datastructuredup。@Tim Ring:。。。同样的问题也适用于普通赋值。低级别
    memdup
    无法正确复制结构这一事实不能有意义地用作反对
    memdup
    的论点。这个答案只是一个煽动性的尝试,试图用不必要的噪音来填补这个问题。@AnT:如果每次我看到这种试图在StackOverflow的行为时都能得到一美元就好了……这是正确的答案。strdup存在的原因不仅仅是将两个调用包装成一个调用,而是因为扫描空字节的逻辑,因为执行malloc+strcpy将导致冗余strlen。这对于memdup是不需要的,这就是为什么当一个简单的malloc+memcpy就足够了时,它不是特别合理的原因。@rdb memdup和memcpy一样,可以接受一个大小参数。我觉得这不是一个令人信服的答案。@rdb是的,
    strdup
    将三个调用包装成一个调用,
    strlen
    调用肯定不是多余的-您需要以某种方式确定字符串的长度(或所需的内存量)。通常,在复制字符串之前需要分配内存,在这种情况下,基本上需要调用
    strlen
    malloc
    strcpy
    按顺序排列。
    strlen
    +
    malloc
    +
    memcpy
    可能更有效。这并不能回答三个具体问题中的任何一个questions@Hooper好,实际上,NUL字节是从以NUL结尾的src字符串复制而来的。这是唯一一个实际回答任何问题的响应。
    int some_function(const struct some_struct *some_const_data)
    {
        struct some_struct *my_mutable_copy;
    
        my_mutable_copy = memdup(some_const_data, sizeof *some_const_data);
        if (my_mutable_copy == NULL)
            return -1;
    
        ...
    
        return 0;
    }