performing a "deep copy" on a nested structure

A

Alfonso Morra

Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET
}ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
Key key ;
ValueTypeEnum type ;
Value value ;
size_t size ;
}MotherStruct ;


Pseudo code:
=============

MotherStruct *pMS_source = (MotherStruct*)calloc(1, sizeof(MotherStruct));

pMS_source->hdr = CreateHeader();
pMS_source->subject = strdup("Test Subject") ;
pMS_source->key = CreateKey("Test", 2000) ;
pMS_source->type = VAL_STRING ;
pMS_source->value.sval = strdup("Homer Simpson") ;
pMS_source->size = /* How do I calculate this ? */


void MakeMSClone(MotherStruct *pMS_Dest, const MotherStruct *pMS_source) {
memmove(pMS_dest,pMS_source, pMS_Source->size) ;

}



MTIA
 
F

Flash Gordon

Alfonso said:
Hi,

I have the ff data types :

Sorry, but I work on the ff library and I don't recognise them ;-)

Seriously, how is anyone meant to know what you mean by ff in the above
statement.
typedef struct {
Header *hdr ;
char *subject ;
Key key ;
ValueTypeEnum type ;
Value value ;
size_t size ;
}MotherStruct ;

Pseudo code:
=============

It is better to post actual compilable code, or as close as you can get
to compilable as possible than pseudo code. Obviously when your problem
is "why doesn't this compile" we don't expect it to compile.
MotherStruct *pMS_source = (MotherStruct*)calloc(1, sizeof(MotherStruct));

You don't need to cast the result of malloc/calloc and if the compiler
complains when you don't you have done something wrong. Also, you can
use the size of what you are pointing at and simplify it to
MotherStruct *pMS_source = calloc(1, sizeof *pMS_source);
However, calloc sets all bits zero which is not necessarily how a null
pointer is represented
pMS_source->hdr = CreateHeader();
pMS_source->subject = strdup("Test Subject") ;
pMS_source->key = CreateKey("Test", 2000) ;
pMS_source->type = VAL_STRING ;
pMS_source->value.sval = strdup("Homer Simpson") ;

You have just overwritten all the fields, so why did you bother with
calloc? Why not use malloc and save having the space initialised to all
bits zeros.

Also, strdup is not a standard C function and it is *not* available on
all systems.
pMS_source->size = /* How do I calculate this ? */

That depends on what it is meant to contain.
void MakeMSClone(MotherStruct *pMS_Dest, const MotherStruct *pMS_source) {
memmove(pMS_dest,pMS_source, pMS_Source->size) ;

Assuming that pMS_dest and pMS_source cannot overlap, which I am
guessing is a requirement, you could use memcpy instead of memmove. I
tend to reserve memmove for when it is legal for the source and
destinations to overlap.

Based on this you wanted
pMS_source->size = sizeof *pMS_source;
However, if that was what you want to use the size of you don't need it
at all since you could do:
memmove(pMS_dest,pMS_source, sizeof *pMS_source);

I think your problem is probably that you have not yet understood that
memmove and memcpy do NOT perform a deep copy. I.e. after the copy
pMS_dest->subject and pMS_source->subject will point to the SAME
location. So if you then did
pMS_source->subject[0]='A';
you would affect both of them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,998
Messages
2,570,242
Members
46,834
Latest member
vina0631

Latest Threads

Top