c memcpy按值构造

问题描述 投票:3回答:3

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

/* 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;
}

这里是小提琴http://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会发生变化?

请注意,在没有struct的情况下执行相同的操作可以按预期工作:http://cpp.sh/6qevd

c memcpy
3个回答
3
投票

当您创建该副本时,两个结构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也指向这个新字符串。


2
投票

如果仅复制该结构,则将覆盖指针,而不是其指向的指针。您可能想做的是代替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是名称中的字符数加上字符串nul-terminator,对realloc的调用将更改p2.name的大小以使其匹配。现在,确保有足够的语音提示,您可以将第一个名字memcpy改成第二个名字。

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

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都可能失败,并且将返回NULL,因此,最好始终进行检查。


1
投票

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

memcpy ( p2.name, p1.name, SIZE );
© www.soinside.com 2019 - 2024. All rights reserved.