c memcpy 按值结构

c memcpy struct by value

我只是想将一个结构复制到另一个结构(按值复制,而不是按引用复制)。这是完整的工作代码

/* memcpy example */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE (80*sizeof(char))

typedef struct {
    char* name;
} person;

int main ()
{
  person p1;
  p1.name = (char*) malloc( SIZE );

  person p2;
  p2.name = (char*) malloc( SIZE );

  // set p1
  strcpy(p1.name, "John");

  // copy p1 > p2
  memcpy ( &p2, &p1, SIZE );

  printf ("p1.name: %s (%u)\n", p1.name, &p1.name );
  printf ("p2.name: %s (%u)\n", p2.name, &p2.name );

  // change p1 only
  printf("Changing p1.name\n");
  strcpy(p1.name, "ONLY p1.name Changed");

  // now, why did p2 change?
  printf ("p1.name: %s (%u)\n", p1.name, &p1.name );
  printf ("p2.name: %s (%u)\n", p2.name, &p2.name );

  free(p1.name);
  free(p2.name);

  return 0;
}

这里是fiddlehttp://cpp.sh/57skb

该代码输出

p1.name: John (0x791b3cdd6270)
p2.name: John (0x791b3cdd6280)
Changing p1.name
p1.name: ONLY p1.name Changed (0x791b3cdd6270)
p2.name: ONLY p1.name Changed (0x791b3cdd6280)

预期输出为

p1.name: John (0x791b3cdd6270)
p2.name: John (0x791b3cdd6280)
Changing p1.name
p1.name: ONLY p1.name Changed (0x791b3cdd6270)
p2.name: John (0x791b3cdd6280)

问题:为什么p2变了?

请注意,在没有结构的情况下做同样的事情会按预期工作: http://cpp.sh/6qevd

您需要复制分配的内存区域而不是结构本身

memcpy ( p2.name, p1.name, SIZE );

当你制作那个副本时,两个结构 name 成员将具有相同的值,因此它们指向相同的内存位置。您的代码没有显示这一点,因为您没有正确打印指针值。试试这个,看看他们确实是一样的

  printf ("p1.name: %s (%p)\n", p1.name, p1.name );
  printf ("p2.name: %s (%p)\n", p2.name, p2.name );

输出

p1.name: John (0x3ee8d60)
p2.name: John (0x3ee8d60)

p2strcpy(p1.name, "ONLY p1.name Changed");之后没有变化。 p2.name 也指向这个新字符串。

如果您只是复制结构,那么您将覆盖指针,而不是它指向的内容。你可能想要做的而不是你的 memcpy 是这样的:

size_t bytes = strlen(p1.name)+1;
p2.name = realloc(p2.name, bytes);
if (p2.name != NULL) {
    memcpy(p2.name, p1.name, bytes);
}

此处,bytes 是名称中的字符数加上字符串空终止符,对 realloc 的调用会更改 p2.name 的大小以匹配它。现在,保证有足够的空间,你可以memcpy名字变成第二个。

这里使用realloc可能效率不高,因为它保留了我们不需要的p2.name的原始内容。另一种方法是先释放旧字符串,然后再为新字符串分配 space:

size_t bytes = strlen(p1.name)+1;
free(p2.name);
p2.name = malloc(bytes);
if (p2.name != NULL) {
    memcpy(p2.name, p1.name, bytes);
}

请注意 malloc 和 realloc 都可能失败,如果您的程序内存不足,它们将 return NULL,因此最好经常检查它。