C语言 如何处理带指针结构的赋值操作?

hc8w905p  于 2023-02-11  发布在  其他
关注(0)|答案(2)|浏览(129)

我有一个结构定义,我需要控制的赋值运算符。这里是一些例子的代码,不工作,我想要的。

struct jsonobject {
    struct jsonobject* children[100];
};

int main(int argc, const char * argv[]) {
    struct jsonobject obj;
    struct jsonobject obj2;
    
    obj2 = obj; // Problem is here.
    
    return 0;
}

问题是obj2 = obj行执行了obj的浅拷贝,而我需要它来执行深拷贝,我应该如何处理这种情况呢?

neekobn8

neekobn81#

  • memcpy(&obj2, &obj, sizeof obj)与本例中的obj2 = obj类似,创建了一个浅副本(如果对象包含指针,则复制这些指针,而不是复制它们指向的任何对象)。
  • 您需要一个(自定义)函数来创建深层副本。除非使用sentinel(NULL),否则您可能希望在结构体中存储子级的数量。

JSON库附带了合适的函数,通常还有一种通过引用计数共享数据的机制。

5anewei6

5anewei62#

您可以编写自己的函数来递归执行深度复制。下面是使用malloc为复制分配内存的演示:

#include <stdio.h>
#include <stdlib.h>

#define MAX_CHILDREN 5

struct jsonobject {
    struct jsonobject* children[MAX_CHILDREN];
};

void deep_print( const struct jsonobject *obj );
struct jsonobject *deep_copy( const struct jsonobject *src );
void deep_free( struct jsonobject *obj );

int main( void )
{
    //construct jsonobject with two layers of children
    struct jsonobject child3child1 =
    {
        {
            NULL,
            NULL,
            NULL,
            NULL,
            NULL
        }
    };
    struct jsonobject child1 =
    {
        {
            NULL,
            NULL,
            NULL,
            NULL,
            NULL
        }
    };
    struct jsonobject child3 =
    {
        {
            NULL,
            &child3child1,
            NULL,
            NULL,
            NULL
        }
    };
    struct jsonobject root =
    {
        {
            NULL,
            &child1,
            NULL,
            &child3,
            NULL
        }
    };

    //deep print the source data
    printf( "Deep print of source data: \n\n" );
    deep_print( &root );

    //perform the deep copy
    struct jsonobject *copy = deep_copy( &root );

    //deep print the copied data
    printf( "\n\nDeep print of copied data: \n\n" );
    deep_print( copy );

    //cleanup
    deep_free( copy );
}

void deep_print( const struct jsonobject *obj )
{
    // NOTE: This function is not thread-safe, because of the use
    //       of this static variable.
    static int depth = 0;

    for ( int i = 0; i < MAX_CHILDREN; i++ )
    {
        //add indentation according to depth
        for ( int j = 0; j < depth; j++ )
            printf( "----" );

        if ( obj->children[i] == NULL )
        {
            printf( "children[%d] is NULL\n", i );
        }
        else
        {
            printf(
                "children[%d] points to %p which contains the following:\n",
                i, (void*)obj->children[i]
            );
            depth++;
            deep_print( obj->children[i] );
            depth--;
        }
    }
}

struct jsonobject *deep_copy( const struct jsonobject *src )
{
    //allocate memory for new struct
    struct jsonobject *new_struct = malloc( sizeof *new_struct );
    if ( new_struct == NULL )
    {
        fprintf( stderr, "Memory allocation failure!\n" );
        exit( EXIT_FAILURE );
    }

    //recursively copy all children
    for ( int i = 0; i < MAX_CHILDREN; i++ )
    {
        if ( src->children[i] == NULL )
        {
            new_struct->children[i] = NULL;
        }
        else
        {
            //perform a recursive deep copy
            new_struct->children[i] = deep_copy( src->children[i] );
        }
    }

    return new_struct;
}

void deep_free( struct jsonobject *obj )
{
    for ( int i = 0; i < MAX_CHILDREN; i++ )
    {
        if ( obj->children[i] != NULL )
        {
            deep_free( obj->children[i] );
        }
    }

    free( obj );
}

出于演示的目的,我将MAX_CHILDREN100简化为5。对于问题中的代码,您希望MAX_CHILDREN的值为100
此演示程序具有以下输出:

Deep print of source data: 

children[0] is NULL
children[1] points to 0x7ffc58161500 which contains the following:
----children[0] is NULL
----children[1] is NULL
----children[2] is NULL
----children[3] is NULL
----children[4] is NULL
children[2] is NULL
children[3] points to 0x7ffc58161550 which contains the following:
----children[0] is NULL
----children[1] points to 0x7ffc581614b0 which contains the following:
--------children[0] is NULL
--------children[1] is NULL
--------children[2] is NULL
--------children[3] is NULL
--------children[4] is NULL
----children[2] is NULL
----children[3] is NULL
----children[4] is NULL
children[4] is NULL

Deep print of copied data: 

children[0] is NULL
children[1] points to 0x604000000050 which contains the following:
----children[0] is NULL
----children[1] is NULL
----children[2] is NULL
----children[3] is NULL
----children[4] is NULL
children[2] is NULL
children[3] points to 0x604000000090 which contains the following:
----children[0] is NULL
----children[1] points to 0x6040000000d0 which contains the following:
--------children[0] is NULL
--------children[1] is NULL
--------children[2] is NULL
--------children[3] is NULL
--------children[4] is NULL
----children[2] is NULL
----children[3] is NULL
----children[4] is NULL
children[4] is NULL

如您所见,源数据的结构已成功复制。此外,复制数据的子级地址与源数据的子级地址不同。这证明执行的是深层复制,而不是浅层复制。

相关问题