C语言中结构复制的行为

时间:2016-03-22 17:15:58

标签: c struct

我一直在阅读关于如何在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

此代码是否会显示深层副本,或者我是否误解了此处发生的事情?

4 个答案:

答案 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;

现在qp具有相同的字段值,但指向不同的内存块。

深层复制需要额外的努力;必须遍历结构中的任何指针并复制其内容。有关详细说明,请参阅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.

ba的浅表副本,因为指向的成员指向相同的内存。

深度复制

深层复制意味着指向的成员也是重复的。它会沿着这些方向发展:

#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进行测试。