tags:

views:

117

answers:

6

This ought to simple. Say we have a struct from a library that doesn't offer copying facilities. Is there an easy way to copy a variable of the type of that struct to a new variable of the same type without doing assignments for each of its sub members? Or does one have to be making special copying functions?

+1  A: 

Keep in mind that it might not be safe to do per-member copy of a structure; for instance, it may hold pointers, and just copying those pointers might not be a great idea if you want an actual copy of the data. However, when it is safe to do it, you may use memcpy save yourself some keystrokes.

struct foo a, b;

// let the third-party lib fill the struct
thirdPartyLibraryCallInvolvingTheFooStruct(&a);

// now we want to copy a to b
memcpy(&b, &a, sizeof b);

Don't forget to read the manpage for more infos!

zneak
I just love it when people downvote without telling why.
zneak
No down-vote, but "b = a;" is way fewer keystrokes than what you propose... which is probably why someone down-voted you.
Peter K.
If you use memcpy, compiler won't do type checking.
Nyan
You don't know how the third-party filled the struct. It's best that the third party provide its own struct copy function rather than using memcpy(), unless you know the details of this structure.
@tchen: The OP said that the library he is using does not offer its own function, that's the whole point of the question.
dreamlax
Thanks for pointing that out. I read it and then forgot about it when I scrolled down to read the comments.
+3  A: 

This sounds like the classic deep copy vs shallow copy topic.

You could copy the variable (shallow copy) with a memcpy operation.

If the struct holds references to other varibles, then this might not be enough and you should implement a more sofisticated (deep) copy.

mcabral
A: 

You could use the memcpy function. This sets a contiguous area of memory, just copying bit for bit; ignoring whether it's a series of ints, or a char array, or whatever.

Smashery
+7  A: 

Well, struct types are assignable in C:

struct SomeStruct s, d;
...
d = s;

It doesn't matter, where they are defined. And there's no need to copy "each of the sub members". Where did you even get the idea about copying it member by member?

Of course, the assignment will perform shallow copying only. If you need deep copying, you need a library-provided copying routine. If there's none, you will have to implement it yourself. In order to do that you will need full knowledge of the actual deep-memory organization of the structure. If you don't know it (i.e. if it is not documented), you are out of luck - proper deep-copying is impossible.

AndreyT
I was going to say, all these methods involving `memcpy` when a simple `=` is all that's needed.
dreamlax
if the struct holds pointers to other values, then assiging the struct won't make a copy (semantically speaking)
mcabral
@dreamlax: The weird habit of using `memcpy` in this case is probably one of the most ridiculous things one can see in C code.
AndreyT
@mcabral: Neither will any of the other solutions provided here.
dreamlax
uhm, ye my question proves silly but at least it's amusing seeing so many other answers that avoid the obvious:D
Lela Dax
Steve Fallows
@mcabral: "Holds pointers" is not the right criterion. "Owns deeper-level memory" - that would be the situation when shallow copying is not sufficient. If the structure "holds pointers" but doesn't own the pointed memory, shallow copying will suffice.
AndreyT
AndreyT
Using `memcpy` (and an initial `memset` to zero) is essential if you want to be able to later use `memcmp` to compare for equality. The assignment operator is not guaranteed to copy padding bytes.
R..
@R..: Well, yes. Although I'm not sure the language specification guarantees the stability of the padding area after you `memset` it to zero. And I'm certainly not a big user of `memcmp` for struct comparison (don't remember ever using it for that purpose).
AndreyT
+2  A: 

C supports struct assignment natively, so if a per-member copy is safe/effective, you can just use direct assignment:

typedef struct { 
    int v1, v2;
    float f1;
} A;

A a = { 0, 2, 1.5f };

A b;
b = a;
Jerry Coffin
... although what you've shown is technically initialization, not assignment.
Charles Bailey
@Charles: "was" -- now fixed.
Jerry Coffin
+2  A: 

It has already been explained that one may use simple assignment for structs, but perhaps an interesting characteristic of this technique is that it even allows you to copy structs containing arrays despite arrays being unassignable. More importantly, it demonstrates that it is not always possible to copy a struct just by assigning to its members individually.

For example:

typedef struct {
    char data[100];
} string;

string a = {"Hello world!"};
string b;

b = a; // works!

puts(b.data); // writes "Hello world!" to standard out.

b.data = a.data; // oops, doesn't work!
dreamlax
Seems like a glitch in the Matrix (C standard advancing in a feature while leaving behind features that could theoretically be its predecessors).
Lela Dax