我一直在阅读关于如何在C中复制结构的网站上的一些问题。我一直在玩一些代码,试图理解“浅”复制之间的区别(简单地指定新结构)指向第一个struct的内存地址的指针和'deep'复制(其中数据被逐个成员复制到一个新的内存块中)。
我创建了以下代码,假设它会显示“浅”复制行为:
#include <stdio.h>
struct tester
{
int blob;
int glob;
char* doob[10];
};
int main (void)
{
//initializing first structure
struct tester yoob;
yoob.blob = 1;
yoob.glob = 2;
*yoob.doob = "wenises";
//initializing second structure without filling members
struct tester newyoob;
newyoob = yoob;
//assumed this line would simply copy the address pointed to by 'yoob'
//printing values to show that they are the same initially
printf("Before modifying:\n");
printf("yoob blob: %i\n", yoob.blob);
printf("newyoob blob: %i\n", newyoob.blob);
//modifying 'blob' in second structure. Assumed this would be mirrored by first struct
newyoob.blob = 3;
//printing new int values
printf("\nAfter modifying:\n");
printf("yoob blob: %i\n", yoob.blob);
printf("newyoob blob: %i\n", newyoob.blob);
//printing memory addresses
printf("\nStruct memory addresses:\n");
printf("yoob address: %p\n", &yoob);
printf("newyoob address: %p\n", &newyoob);
}
跑步时的输出:
Before modifying:
yoob blob: 1
newyoob blob: 1
After modifying:
yoob blob: 1
newyoob blob: 3
Struct memory addresses:
yoob address: 0x7fff3cd98d08
newyoob address: 0x7fff3cd98cb0
此代码是否会显示深层副本,或者我是否误解了此处发生的事情?
答案 0 :(得分:5)
浅层与深层复制问题仅与指针有关。给定类型struct foo
:
struct foo a = /* initialize */;
struct foo b = a;
a
中的所有值都会复制到b
。 它们不是同一个变量。
然而,使用指针:
struct foo *p = calloc(1, sizeof *p);
struct foo *q = p;
q
现在指向与p
相同的内存;没有发生任何复制(一旦获得free
d,你就会冒着悬空指针的风险)。这是指针别名。为了做一个浅拷贝,可以做:
struct foo *p = calloc(1, sizeof *p);
/* assign to p's fields... */
struct foo *q = calloc(1, sizeof *q);
*q = *p;
现在q
与p
具有相同的字段值,但指向不同的内存块。
深层复制需要额外的努力;必须遍历结构中的任何指针并复制其内容。有关详细说明,请参阅this post。
答案 1 :(得分:3)
当您使用newyoob = yoob;
时,编译器会创建代码来为您复制结构。
关于复制的一个重要说明:它是浅薄的。这意味着如果你有例如一个包含指针的结构,它只是要复制的实际指针,而不是它们所指向的指针,因此在复制后你将有两个指针指向同一个内存。
答案 2 :(得分:1)
你的概念&#34;浅拷贝&#34;是错的。代码
newyoob = yoob;
事实上正在为newyoob创建一个shallow copy的yoob。您的变量 yoob 和 newyoob 是单独的内存分配。
现在,如果你这样做了
struct tester* newyoob = &yoob;
然后newyoob和yoob是&#34;相同&#34; - 但同样,引用相同内存区域的两个变量不被视为副本。
答案 3 :(得分:0)
typedef struct tester {
int someInt;
char* someString;
} tester;
然后您将一个实例分配给另一个实例:
tester a = {1, "hohohahah"};
tester b = a;
a
的成员将按值复制,包括指针。这意味着:
a.someString == b.someString // True: comparing addresses and addresses are the same.
b
是a
的浅表副本,因为指向的成员指向相同的内存。
深层复制意味着指向的成员也是重复的。它会沿着这些方向发展:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct tester {
int someInt;
char* someString;
} tester;
void deepcopy_tester(tester *in, tester *out) {
out->someInt = in->someInt;
out->someString = malloc(strlen(in->someString)+1);
strcpy(out->someString, in->someString);
}
int main() {
tester t1 = {1, "Yo"};
tester t2 = {0, NULL};
deepcopy_tester(&t1, &t2);
printf("%s\na", t2.someString);
}
此代码应该可以使用,只需使用gcc进行测试。