structures --assignment?

M

Michael

Hi there,
I've got a simple (newbee)-question.
Is the following thing right?

struct x {
int a;
int b;
}
...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

I think there is something in the FAQ, but
I'm not sure if I took it right. The above
code works with the compiler I'm using, but
I'm sure if this kind of statement is allowed.
Thanks for any help
Michael
 
A

Alex

Michael said:
struct x {
int a;
int b;
} ; /* Don't forget :) */
...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

Yes, structure assignment is fine. But if you have pointers in the struct,
you might need to make copies of the data pointed to (a so-called "deep
copy"). (An alternative is reference counting, but that's a bit more
complicated.)
 
R

Richard Bos

Michael said:
Is the following thing right?

struct x test1;
struct x test2;

test2 = test1

Sure, perfectly correct.

Note, though, that it is not specified whether the copying is done
bytewise or per member; if the struct contains padding, then
memcmp(&test1, &test2, sizeof test1) may or may not succeed depending on
your implementation. All individual members will compare equal, though.

Richard
 
M

Michael

Hey,
thank you for the fast answers. So I don't
bother anymore.

@Alex: Mea culpa, but whew the code wasn't taken
out of some program ;-)

Have a nice day
Michael
 
P

pete

Michael said:
Hi there,
I've got a simple (newbee)-question.
Is the following thing right?

struct x {
int a;
int b;
}
...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

I think there is something in the FAQ, but
I'm not sure if I took it right. The above
code works with the compiler I'm using, but
I'm sure if this kind of statement is allowed.

It's allowed. What you can't do however,
is compare structures by operators.

test2 == test1
test2 != test1
 
M

Martin Ambuhl

Michael said:
Hi there,
I've got a simple (newbee)-question.
Is the following thing right?

struct x {
int a;
int b;
}
^^^^^
No, you are missing a semicolon.
...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1
^^^^^
No, you are missing another semicolon.
 
E

E. Robert Tisdale

Michael said:
Is the following thing right?

struct x {
int a;
int b;
};
// ...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

Bad idea. Try

x x_create(int a, int b) {
struct x result;
result.a = a;
result.b = b;
return result;
}

const struct x test1 = x_create(17, 33);
const struct x test2 = test1;

Try to avoid uninitialized objects.
Try to avoid variables if possible.
Define constants instead.
 
T

Tom St Denis

E. Robert Tisdale said:
Michael said:
Is the following thing right?

struct x {
int a;
int b;
};
// ...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

Bad idea. Try

x x_create(int a, int b) {
struct x result;
result.a = a;
result.b = b;
return result;
}

How is this a good idea? "result" is in the scope of the function only and
UNDEFINED elsewhere.
const struct x test1 = x_create(17, 33);

This is not valid.

<snip rest>

Tom
 
J

Jarno A Wuolijoki

struct x x_create(int a, int b) {
How is this a good idea? "result" is in the scope of the function only and
UNDEFINED elsewhere.

So? Are you somwhow going to access "result" after the function returns?
 
A

Allin Cottrell

Tom said:
Michael wrote:

Is the following thing right?

struct x {
int a;
int b;
};
// ...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

Bad idea. Try

x x_create(int a, int b) {
struct x result;
result.a = a;
result.b = b;
return result;
}


How is this a good idea? "result" is in the scope of the function only and
UNDEFINED elsewhere.

const struct x test1 = x_create(17, 33);


This is not valid.

On the contrary, it's fine. Your point about scope has no more force
against the example above, with return of a struct, than it would have
against the following (pointless but valid) code:

int set_int (int val)
{
int i = val;
return i;
}

int j = set_int(10);

That is, the variable i falls out of scope when set_int() returns, but
its value is nonetheless successfully transfered to j.
 
E

E. Robert Tisdale

Jarno said:
struct x x_create(int a, int b) {

Are you somehow going to access "result" after the function returns?

I'm using it like this:

const struct x test1 = x_create(17, 33);

You really need to appreciate the *magic*
of a good optimizing C compiler here.

The C compiler reserves automatic storage for test1
then calls x_create passing a pointer to test1
(typically as a [hidden] first argument) to x_create.
In effect, the compiler calls:

x_create(&test1, 17, 33);

in this case.

The C compiler recognizes result as a reference to the return value:

struct x* x_create(struct x* pReturnValue, int a, int b) {
pReturnValue->a = a;
pReturnValue->b = b;
return pReturnValue;
}

so that x_create actually initializes test1 directly!

In fact, using my GNU C compiler, I can define

struct x* x_create(struct x*, int, int);

as an external function in another file then declare

extern struct x x_create(int a, int b);

and invoke

const struct x test1 = x_create(17, 13);

in my main program and test1 is initialized as expected.

Most modern C compilers implement this optimization.
 
N

Nick Landsberg

E. Robert Tisdale wrote:

[ Much Snipped ]
Most modern C compilers implement this optimization.

"most" is not a number. (NAN) ...

And what if the compiler you have to work with
tomorrow is an ancient one which was used to generate
the code for "Rover?"

What will it do with those constructs?

What code will it actually generate?

"Undefined Behavior" comes to mind as a probable result.

Resident Skeptic and Professional Paranoid.
 
T

Tom St Denis

Jarno A Wuolijoki said:
struct x x_create(int a, int b) {


So? Are you somwhow going to access "result" after the function returns?

Oh shit I guess you can do this. Hmm, I don't normally pass structures [or
return them] as arguments. Just doesn't seem right for C.

Tom
 
E

E. Robert Tisdale

Tom said:
Oh shit. I guess you can do this.
Hmm, I don't normally pass structures [or return them] as arguments.
Just doesn't seem right for C.

According to Brian W. Kernighan and Dennis M. Ritchie,
"The C Programming Language" (1978), Chapter 6: Structures,
Subsection 2: Structures and Functions, page 121:

"There are a number of restrictions on C structures.
The essential rules are that the only operations
that you can perform on a structure are
take its address with &, and access one of its members.
This implies that
structures may not be assigned to or copied as a unit.
and that they can not be passed to or returned from functions.
(These restrictions will be removed in forth-coming versions.)"

Indeed, these restrictions have long since been removed.
You just haven't kept up with the C language.
 
J

Jack Klein

Michael said:
Is the following thing right?

struct x {
int a;
int b;
};
// ...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

Bad idea. Try

Good idea. Perfectly well defined C. All members of test2 will
compare identical to test1.
x x_create(int a, int b) {
struct x result;
result.a = a;
result.b = b;
return result;
}

const struct x test1 = x_create(17, 33);
const struct x test2 = test1;

Idiotic, unless your structure points to dynamic memory and you need
to do a deep, rather than shallow, copy. And for that your sample
code would do a shallow copy as well.
Try to avoid uninitialized objects.

Where in the OP's post did he make use of an indeterminate object?
Try to avoid variables if possible.

Read the line you wrote above over and over again until you finally
see its absurdity.
Define constants instead.

Instead of what?
 
M

Michael

Hi there,
as I already stated I'm not an expert in C.
After reading my post again I have to admit
that I didn't point out exactly the things
I want to know. But most of you anticipate
the right thing, not the missing colons but
the structure-assignment :)
Ok, so far I get a lot of answers, thanks for that.

I'm I right that
a) The assignment is legal, but to do it by function
is somehow more flexible e.g. a deep copy can be done
b) If I use structs itself not pointers (return-value),
well I think I do the same thing. <struct> = <struct>
Am I wrong?
I think I shouldn't care about the way the compiler
do it, if the statement itself is legal.(?)

Regards
Michael

Jack Klein schrieb:
 
B

Barry Schwarz

E. Robert Tisdale said:
Michael said:
Is the following thing right?

struct x {
int a;
int b;
};
// ...

struct x test1;
struct x test2;
[.. init test1 somehow]

test2 = test1

Bad idea. Try

x x_create(int a, int b) {
struct x result;
result.a = a;
result.b = b;
return result;
}

How is this a good idea? "result" is in the scope of the function only and
UNDEFINED elsewhere.

While what you say is true for all automatic variables local to the
function, it is not true for the value. If the function were declared
to return an int and the return statement specified result.a, you
would not see a problem even though result.a cannot exist if result
does not.

While it is unusual (or better unpopular) to pass and return structs
as opposed to pointers to structs (because of additional resource
consumption), it is legal. Unlike attempts to return arrays,
returning a struct really returns the complete aggregate value of the
struct, not a pointer to an object which might no longer exist.
This is not valid.

Worked fine on my system.
<snip rest>

Tom



<<Remove the del for email>>
 
B

Barry Schwarz

Jarno said:
struct x x_create(int a, int b) {

Are you somehow going to access "result" after the function returns?

I'm using it like this:

const struct x test1 = x_create(17, 33);

You really need to appreciate the *magic*
of a good optimizing C compiler here.

The C compiler reserves automatic storage for test1
then calls x_create passing a pointer to test1
(typically as a [hidden] first argument) to x_create.
In effect, the compiler calls:

x_create(&test1, 17, 33);

This is utter hogwash. The called function has no idea how the
returned value will be used. It simply returns the value, an
aggregate value in this case, using whatever convention the compiler
writer chooses to establish, and code in the calling program does
whatever is appropriate with this value.
in this case.

The C compiler recognizes result as a reference to the return value:

C does not pass by reference, period.
struct x* x_create(struct x* pReturnValue, int a, int b) {
pReturnValue->a = a;
pReturnValue->b = b;
return pReturnValue;
}

so that x_create actually initializes test1 directly!

Completely irrelevant to your previous discussion.
In fact, using my GNU C compiler, I can define

struct x* x_create(struct x*, int, int);

as an external function in another file then declare

extern struct x x_create(int a, int b);

and invoke

const struct x test1 = x_create(17, 13);

in my main program and test1 is initialized as expected.

Most modern C compilers implement this optimization.

More drivel.


<<Remove the del for email>>
 
B

Barry Schwarz

Hi there,
as I already stated I'm not an expert in C.
After reading my post again I have to admit
that I didn't point out exactly the things
I want to know. But most of you anticipate
the right thing, not the missing colons but
the structure-assignment :)
Ok, so far I get a lot of answers, thanks for that.

I'm I right that
a) The assignment is legal, but to do it by function
is somehow more flexible e.g. a deep copy can be done

Your first clause is correct. Everything after the comma is the
result of being sucked in by a troll and can be safely ignored.
b) If I use structs itself not pointers (return-value),
well I think I do the same thing. <struct> = <struct>
Am I wrong?

No, you are correct. A function can return a struct (actually the
aggregate value of the struct) which can then be used almost
everywhere an actual struct object could be used.

Since it is legal to say
struct_obj1 = struct_obj2;
it is also legal to say
struct_obj1 = function_returning_struct_obj(...);

Since it is legal to say
struct_obj1.member1 = struct_obj2.member1;
it is also legal to say
struct_obj1.member1 = function_returning_struct_obj(...).member1;
I think I shouldn't care about the way the compiler
do it, if the statement itself is legal.(?)

Probably true. Definitely true until you are much more experienced
and write code where performance is almost as important as
correctness.


<<Remove the del for email>>
 
D

Dik T. Winter

> Jarno A Wuolijoki wrote: ....
> In fact, using my GNU C compiler, I can define
>
> struct x* x_create(struct x*, int, int);
>
> as an external function in another file then declare
>
> extern struct x x_create(int a, int b);
>
> and invoke
>
> const struct x test1 = x_create(17, 13);
>
> in my main program and test1 is initialized as expected.
>
> Most modern C compilers implement this optimization.

There are modern C compilers that optimise still better and return
small enough structs through the registers.
 

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
474,137
Messages
2,570,797
Members
47,342
Latest member
eixataze

Latest Threads

Top