Copying structs

S

subnet

Excuse me for the perhaps silly question, but is the following
permitted:

struct mystruct {
int f1;
int f2;
char f3;
float f4;
};

struct mystruct s1, s2;

s1.f1 = 10;
s1.f2 = 15;
s1.f3 = 'a';
s1.f4 = 5.5;

s2 = s1; /* or, if working with (struct mystruct *), even *s2 = *s1
*/

gcc does not warn about anything, and furthermore it seems to work
(ie, all the fields in s2 are copied correctly from s1), but this kind
of operation seems pretty new to me. Do the standards talk about this?

Thanks
 
A

Artie Gold

subnet said:
Excuse me for the perhaps silly question, but is the following
permitted:

struct mystruct {
int f1;
int f2;
char f3;
float f4;
};

struct mystruct s1, s2;

s1.f1 = 10;
s1.f2 = 15;
s1.f3 = 'a';
s1.f4 = 5.5;

s2 = s1; /* or, if working with (struct mystruct *), even *s2 = *s1
*/
gcc does not warn about anything, and furthermore it seems to work
(ie, all the fields in s2 are copied correctly from s1), but this kind
of operation seems pretty new to me. Do the standards talk about this?
Yes. It's perfectly legal (and has been since the first ANSI/ISO C).

In the second case, *s2 = *s1, it's only legal if s2 points to allocated
space (either dynamically allocated or automatic).

HTH,
--ag
 
A

Arthur J. O'Dwyer

Excuse me for the perhaps silly question, but is the following
permitted:
struct mystruct s1, s2;

Yes, that's perfectly valid C code. Structs can also be passed by value
to functions

foo(s1);

and returned from functions

struct s foo(void) {
struct s rc = {0};
return rc;
}

void bar(void) {
struct s tmp;
tmp = foo();
}

All this was introduced in the 1989 Standard, AFAIK. It wasn't present in
a lot of pre-Standard ("K&R") compilers.

(Because it wasn't in K&R, after I learned C I spent several years
avoiding these constructs in the belief that they were "inefficient" ---
what looked like one line of C source code was expanding to several (or
several dozen!) lines of assembly behind my back. But then I realized
that (pragmatically) the 'a=b;' idiom is certainly no worse than the
'a.x=b.x; a.y=b.y; a.z=b.z;' idiom; and (philosophically) it made no sense
to worry about the "expansion" of my code by the compiler if the
alternative was to expand the code myself in the C source!)

Conclusion: Struct assignment is legal. Use it unless you absolutely
must retain portability to pre-C89 implementations.

HTH,
-Arthur
 
D

Dan Pop

In said:
Yes. It's perfectly legal (and has been since the first ANSI/ISO C).

As anticipated by K&R1, it was actually legal since soon after K&R1 went
to print, when Unix V7 was released (it came with a one page addenda to
K&R1 document). At the same time, C acquired enumerated types.

Dan
 
M

Minti

subnet said:
Excuse me for the perhaps silly question, but is the following
permitted:

struct mystruct {
int f1;
int f2;
char f3;
float f4;
};

struct mystruct s1, s2;

s1.f1 = 10;
s1.f2 = 15;
s1.f3 = 'a';
s1.f4 = 5.5;

s2 = s1; /* or, if working with (struct mystruct *), even *s2 = *s1
*/

gcc does not warn about anything, and furthermore it seems to work
(ie, all the fields in s2 are copied correctly from s1), but this kind
of operation seems pretty new to me. Do the standards talk about this?

Thanks

Any specific reason why you think your text book does not talk about this
one? FWIW try this now

#include <stdio.h> // For printf

int main(void)
{

struct myStruct
{
int myArray[256];
};

myStruct myS1, myS2;

for ( int i = 0; i < 256; ++i )
{

myS1.myArray = i;
myS2.myArray = i + 1;
}

myS1 = myS2;

for ( int i = 0; i < 256; ++i)
{
printf("%d", myS1.myArray );
}

return 0;
}


In C when you assign a structure to another, it is nothing more that plain
bit by bit copy.


HTH
--
Imanpreet Singh Arora
Zmoc.Zliamg@Zteerpnami
Remove Z to mail
"Things may come to those who wait, but only the things left by those who
hustle."
Abraham Lincoln
 
M

Mark Piffer

Yes, that's perfectly valid C code. Structs can also be passed by value
to functions

foo(s1);

and returned from functions

struct s foo(void) {
struct s rc = {0};
return rc;
}

void bar(void) {
struct s tmp;
tmp = foo();
}

All this was introduced in the 1989 Standard, AFAIK. It wasn't present in
a lot of pre-Standard ("K&R") compilers.

There's however one "caution!"-sign to be attached to the returning of
structs. Some compilers will use a shared statically allocated memory
area to hold intermediate return objects for struct objects instead of
on the stack, contrary to what a programmers gut feeling would tell
when looking at the syntax and semantics. This means reentrancy is
thrown overboard. While this is a perfectly legal implementation and
covered by the standard, it is extremely annoying when one wants to
build multi-threading or interrupt functions - I ran into this
"feature" with a compiler for a 16 bit microcontroller which is
specifically targeted for multiple tasks on multiple interrupt levels
(the compiler documentation even goes into great detail to explain how
to build multi-tasked programs).

Mark
 
A

Arthur J. O'Dwyer

and returned from functions

struct s foo(void) {
struct s rc = {0};
return rc;
}
[...]
There's however one "caution!"-sign to be attached to the returning of
structs. Some compilers will use a shared statically allocated memory
area to hold intermediate return objects for struct objects instead of
on the stack, contrary to what a programmers gut feeling would tell
when looking at the syntax and semantics. This means reentrancy is
thrown overboard.

Reentrancy in the sense of multi-threaded-ness, yes? I see
multi-threaded-ness being thrown overboard (in the case that one function
writes to the shared "return" buffer before another function has a chance
to read its own data back out of it).
Such an implementation is still safe in single-threaded environments,
though --- you can call a struct-returning function recursively, for
example, and it will still work.

In theory, such an implementation is not significantly different from
one in which all 'int' values are returned in the accumulator register.
It's just that (I presume) most multi-threaded environments somehow make
non-interfering copies of the registers for different threads, but don't
make the same copies of the in-memory "returned struct" buffer.

-Arthur,
single-threaded
 
G

goose

Excuse me for the perhaps silly question, but is the following
permitted:

struct mystruct {
int f1;
int f2;
char f3;
float f4;
};

struct mystruct s1, s2;

s1.f1 = 10;
s1.f2 = 15;
s1.f3 = 'a';
s1.f4 = 5.5;

s2 = s1; /* or, if working with (struct mystruct *), even *s2 = *s1
*/

gcc does not warn about anything, and furthermore it seems to work
(ie, all the fields in s2 are copied correctly from s1), but this kind
of operation seems pretty new to me. Do the standards talk about this?

Perfectly legal as all the other posters have pointed out. The
one thing you should beware off is structs that contain a pointer:

struct person_t {
int age;
char *name;
};

struct person_t leo, lee;

char test_name[] = "LEO";
....

leo.age = 42;
leo.name = test_string;

lee = leo;

printf ("%s\n", leo.f2); /* prints "LEO" as you expect */
printf ("%s\n", lee.f2); /* prints "LEO" as you expect */

lee.name[2] = 'E'; /* change the name from LEO to LEE */

printf ("%s\n", leo.name); /* prints "LEE", even though you think
that it was not modified. */
printf ("%s\n", lee.name); /* prints "LEE" as you expect */


structs that contain a pointer must be assigned carefully, as you
*may* not want the struct being assigned to (on the right hand side
of the equals) pointing to the same piece of data.

hand
goose,
not my /real/ name :)
 
S

subnet

Perfectly legal as all the other posters have pointed out. The
one thing you should beware off is structs that contain a pointer:

Of course: plain s1 = s2 is just a "shallow" copy; I'm aware that to
do a deep copy, if the struct contains pointers, the elements pointed
to by those pointers need to be copied as well, and so on recursively.

Thanks everybody for your answers.
 

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,147
Messages
2,570,835
Members
47,383
Latest member
EzraGiffor

Latest Threads

Top