gpt4 book ai didi

c - 具有指针作为 C 成员的结构的 memcpy

转载 作者:太空狗 更新时间:2023-10-29 15:14:09 25 4
gpt4 key购买 nike

我有一个包含一些指针作为成员的结构,我正在尝试执行 memcpy,有人建议我在这种情况下不应该使用 memcpy,因为 memcpy 执行浅拷贝(意味着它拷贝指针)而不是深拷贝(意味着复制指针指向的内容)。

但我不确定为什么它在以下程序中没有任何区别:请查看代码和输出,并请解释为什么在这种情况下它不是浅拷贝?

#include <stdio.h>
#include <malloc.h>
#include <string.h>

struct student {
char *username;
char *id;
int roll;
};

void print_struct(struct student *);
void print_struct_addr(struct student *);
void changeme(struct student *);

int main (void) {
struct student *student1;
char *name = "ram";
char *id = "200ABCD";
int roll = 34;

student1 = (struct student *)malloc(sizeof(struct student));
student1->username = name;
student1->id = id;
student1->roll = roll;
print_struct_addr(student1);
print_struct(student1);
changeme(student1);
print_struct(student1);
print_struct_addr(student1);
return 0;
}

void print_struct(struct student *s) {
printf("Name: %s\n", s->username);
printf("Id: %s\n", s->id);
printf("R.No: %d\n", s->roll);
return;
}

void print_struct_addr(struct student *s) {
printf("Addr(Name): %x\n", &s->username);
printf("Addr(Id): %x\n", &s->id);
printf("Addr(R.No): %x\n", &s->roll);
return;
}

void changeme(struct student *s) {
struct student *student2;
student2->username = "someone";
student2->id = "200EFGH";
student2->roll = 35;
print_struct_addr(student2);
memcpy(s, student2, sizeof(struct student));
student2->username = "somebodyelse";
return;
}

输出:

Addr(Name): 9b72008
Addr(Id): 9b7200c
Addr(R.No): 9b72010
Name: ram
Id: 200ABCD
R.No: 34
Addr(Name): fa163c
Addr(Id): fa1640
Addr(R.No): fa1644
Name: someone
Id: 200EFGH
R.No: 35
Addr(Name): 9b72008
Addr(Id): 9b7200c
Addr(R.No): 9b72010

如果 memcpy 进行浅拷贝,为什么 student1->username 不是“somebodyelse”。

请解释在哪种情况下,此代码会产生问题,我希望在 main() 中调用 changeme() 后,student1 中有 student2 信息,之后应该能够使用修改后的 student1 数据。

有人建议我不要在这里使用 memcpy(),但它似乎工作正常。

谢谢

这是修改后的代码:但我仍然没有在这里看到浅拷贝的概念:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

struct student {
char *username;
char *id;
int roll;
};

void print_struct(struct student *);
void print_struct_addr(struct student *);
void changeme(struct student *);

int main (void) {
struct student *student1;
char *name = "ram";
char *id = "200ABCD";
int roll = 34;

student1 = malloc(sizeof(*student1));
student1->username = name;
student1->id = id;
student1->roll = roll;
print_struct_addr(student1);
print_struct(student1);
changeme(student1);
print_struct(student1);
print_struct_addr(student1);
return 0;
}

void print_struct(struct student *s) {
printf("Name: %s\n", s->username);
printf("Id: %s\n", s->id);
printf("R.No: %d\n", s->roll);
return;
}

void print_struct_addr(struct student *s) {
printf("Addr(Name): %x\n", &s->username);
printf("Addr(Id): %x\n", &s->id);
printf("Addr(R.No): %x\n", &s->roll);
return;
}

void changeme(struct student *s) {
struct student *student2;
student2 = malloc(sizeof(*s));
student2->username = strdup("someone");
student2->id = strdup("200EFGH");
student2->roll = 35;
print_struct_addr(student2);
memcpy(s, student2, sizeof(struct student));
student2->username = strdup("somebodyelse");
free(student2);
return;
}

最佳答案

这个:

struct student *student2;
student2->username = "someone";
student2->id = "200EFGH";
student2->roll = 35;

正在写入未分配的内存,调用未定义的行为。在写入之前,您需要确保 student2 指向有效的地方。

要么分配它,要么使用一个栈上实例,因为无论如何你只是要从它复制。

当然,初始化student2然后用它覆盖s的整个过程是不必要的复杂,你应该直接修改s

另外,这个:

student1 = (struct student *)malloc(sizeof(struct student));

最好用 C 写成:

student1 = malloc(sizeof *student1);

这会删除 pointless (and potentially dangerous) cast ,并确保大小适合该类型,将程序员检查的依赖项替换为编译器处理的依赖项。

第三,没有意识到您可以对结构进行赋值,这是 C 程序员新手的一个典型“症状”。所以,而不是

memcpy(s, student2, sizeof *s);

你可以这样写:

*s = *student2;

让编译器做正确的事。这可能是一个性能上的胜利,因为该结构可以包含大量填充,分配可以知道这些填充而不是复制这些填充,但是 memcpy() 不能忽略它们。

关于c - 具有指针作为 C 成员的结构的 memcpy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13138567/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com