Copy by value symantics

R

Russell Shaw

Hi,
How do i easily assign one struct to another of a different type?

struct Object object = allocate_object();

struct Widget widget = (struct Widget)object; /* doesn't work */

struct Widget is bigger than struct Object.
 
G

goose

Russell said:
Hi,
How do i easily assign one struct to another of a different type?

struct Object object = allocate_object();

struct Widget widget = (struct Widget)object; /* doesn't work */

struct Widget is bigger than struct Object.

Short answer, possibly not what you are looking for:

memcpy (&widget, &object, sizeof widget);

Long answer:

The surest way of doing this by copying each member
individually. Example:

struct Object object = allocate_object ();

struct Widget widget;

widget.wmember_one = object.omember_one;
widget.wmember_two = object.omember_two;
/* go on in this fashion until you are done */

A better way, IMHO, is to place the two structs into a
union, assign the first, and read from the second; although
this is possibly non-conforming (someone will let us know
here if it is:)

union Both {
struct Object object;
struct Widget widget;
};

struct Widget widget;

Both.object = allocate_object ();
widget = Both.widget;
 
E

Eric Sosman

Russell said:
Hi,
How do i easily assign one struct to another of a different type?

struct Object object = allocate_object();

struct Widget widget = (struct Widget)object; /* doesn't work */

struct Widget is bigger than struct Object.

Why would you expect this to do anything sensible?
If `struct Widget' and `struct Object' are unrelated,

struct Object {
int this, that, the_other;
const char *canonical_name;
};

struct Widget {
struct Widget *link;
double centroid[3];
double coeff_matrix[4][4];
ColorCode hue;
};

.... what meaning would the assignment have?

If there *is* some kind of relationship between
`struct Object' and `struct Widget', describe what it's
like and someone may be able to help -- but for arbitrary
structs of unrelated types, assignment is silly.
 
M

Mark McIntyre

Why would you expect this to do anything sensible?

I imagine this arises from some sort of pseudo OO environment, where
you create a generic object handle, then coerce it to some type. You
see this all the time in the Win32 API.

To the OP: the assigment makes no sense. I suspect you need to be
assigning pointers, not objects?

struct Widget* p_widget = (struct Widget*) &object;

and bear in mind that this may not be legal C, since the members of
object will not be the same as those of *p_widget.
 
E

Eric Sosman

Mark said:
Why would you expect this to do anything sensible?


I imagine this arises from some sort of pseudo OO environment, [...]

As do I, hence the appeal for more information about the
context. It may turn out that `struct Object' is a "prefix"
of `struct Widget', or even an embedded element as in

struct Widget {
struct Object your_honor;
long time_no_see;
double trouble;
short shrift;
};

But the O.P. needs to supply more information before we (or I,
at any rate) can suggest how to proceed.
 
L

Lawrence Kirby

Short answer, possibly not what you are looking for:

memcpy (&widget, &object, sizeof widget);

Unless there is some relationship between object and widget, which needs
to be specified, this is simply broken code.
Long answer:

The surest way of doing this by copying each member
individually. Example:

struct Object object = allocate_object ();

struct Widget widget;

widget.wmember_one = object.omember_one;
widget.wmember_two = object.omember_two;
/* go on in this fashion until you are done */

Yes, that's fair, and implies a field relationship between widget and
object
A better way, IMHO, is to place the two structs into a union, assign the
first, and read from the second; although this is possibly
non-conforming (someone will let us know here if it is:)

union Both {
struct Object object;
struct Widget widget;
};

struct Widget widget;

Both.object = allocate_object ();
widget = Both.widget;

In general this is a very nasty thing to do with unions. Again there has
to be a relationship between object and widget for this to m\ke any sense
at all. In that case the memcoy() is probably better, it certainly avoids
a double copy.

The answer to this is to specify the relationship between object and
widget and work from there.

Lawrence
 
R

Russell Shaw

Eric said:
Mark said:
How do i easily assign one struct to another of a different type?

struct Object object = allocate_object();
struct Widget widget = (struct Widget)object; /* doesn't work */

Why would you expect this to do anything sensible?

I imagine this arises from some sort of pseudo OO environment, [...]


As do I, hence the appeal for more information about the
context. It may turn out that `struct Object' is a "prefix"
of `struct Widget', or even an embedded element as in

struct Widget {
struct Object your_honor;
long time_no_see;
double trouble;
short shrift;
};

But the O.P. needs to supply more information before we (or I,
at any rate) can suggest how to proceed.

The above struct nesting is what i have.

I was hoping to do something like:

struct Widget widget = (struct Widget)allocate_object1();


The other way of doing it is of course:

struct Widget widget;

allocate_object2((struct Object*)&widget);


allocate_object() deals only with stack memory (ie, no mallocs).
 
E

Eric Sosman

Russell said:
Eric Sosman wrote:
[...] It may turn out that `struct Object' is a "prefix"
of `struct Widget', or even an embedded element as in

struct Widget {
struct Object your_honor;
long time_no_see;
double trouble;
short shrift;
};

But the O.P. needs to supply more information before we (or I,
at any rate) can suggest how to proceed.

The above struct nesting is what i have.

I was hoping to do something like:

struct Widget widget = (struct Widget)allocate_object1();

struct Widget widget;
widget.your_honor = allocate_object1();
widget.time_no_see = ...
widget.trouble = ...
widget.shrift = ...
The other way of doing it is of course:

struct Widget widget;

allocate_object2((struct Object*)&widget);

This will work if you happen to know that the struct Object
is the first element in the struct Widget (and if you're 100%
certain nobody will ever change that). A cleaner and possibly
safer alternative is

allocate_object2(&widget.your_honor);
widget.time_no_see = ...
...
allocate_object() deals only with stack memory (ie, no mallocs).

If by this you mean that allocate_object1() returns a
`struct Object' (not a `struct Object*') and that a..2()
operates on the target of its `struct Object*' argument,
all is well. If you mean something else, I've failed to
grasp it.
 
L

Lawrence Kirby

Eric said:
Mark said:
On Mon, 06 Jun 2005 14:40:57 -0400, in comp.lang.c , Eric Sosman

How do i easily assign one struct to another of a different type?

struct Object object = allocate_object();
struct Widget widget = (struct Widget)object; /* doesn't work */

Why would you expect this to do anything sensible?

I imagine this arises from some sort of pseudo OO environment, [...]


As do I, hence the appeal for more information about the
context. It may turn out that `struct Object' is a "prefix"
of `struct Widget', or even an embedded element as in

struct Widget {
struct Object your_honor;
long time_no_see;
double trouble;
short shrift;
};

But the O.P. needs to supply more information before we (or I,
at any rate) can suggest how to proceed.

The above struct nesting is what i have.

I was hoping to do something like:

struct Widget widget = (struct Widget)allocate_object1();

No, you can't cast to a structure type in C.

Anyway what is allocate_object1() actually returning? Since C doesn't have
references it would make most sense for this to be a pointer. In which
case you would need to cast it to a pointer of the appropriate type. And
it had better be a struct Widget that allocate_object1() allocates, or
I guess you could get away with a "subtype" of that i.e. one with a
struct widget as its first member.
The other way of doing it is of course:

struct Widget widget;

allocate_object2((struct Object*)&widget);

Again, what type of object is allocate_object2() supposed to be
allocating? In fact in this case it isn't allocating anything, probably
just filling in fields, but for what? If is just a struct Object then the
rest of the fields in struct Widget are going to be left uninitialised.
There's the same problem in the first example. But if that isn't a problem
then this is a reasonable way to handle it in C.

You really need to explain what it is you are trying to achieve with
this operation.
allocate_object() deals only with stack memory (ie, no mallocs).

OK, I see why the first example is returning a structure rather than a
pointer then. Of course you could write

widget.your_honor = allocate_object1();

but I gues you want something with the feel of inheritance.

Lawrence
 
C

CBFalconer

Lawrence said:
. snip ...

In general this is a very nasty thing to do with unions. Again
there has to be a relationship between object and widget for this
to m\ke any sense at all. In that case the memcoy() is probably
better, it certainly avoids a double copy.

It is all completely non-portable. Behaviour is undefined when
reading something from a union of a different type than that last
put into it.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
 
M

Malcolm

Russell Shaw said:
How do i easily assign one struct to another of a different type?

struct Object object = allocate_object();

struct Widget widget = (struct Widget)object; /* doesn't work */

struct Widget is bigger than struct Object.
A C struct is just a layout of more basic types in memory.
A C pointer is just a variable that holds an address.

So if

struct Object
{
int x;
int y;
int z;
};

struct Widget
{
struct Object obj;
int special;
};

Then you can create a struct Widget, and then copy an "Object" to the obj
member.

If you know that an Object is the first member of "Widget" then you can also
mess around with the C type system by interconverting pointer to objects and
widgets. Generally this is a bad idea, at least until you are familiar
enough with C to know what you are doing.
 

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,755
Messages
2,569,536
Members
45,016
Latest member
TatianaCha

Latest Threads

Top