473,606 Members | 2,200 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Copying a struct to a larger struct?

I want to use memcpy to copy the contents of one struct to another
which is a superset of the original struct (the second struct has extra
members at the end). I wrote a small program to test this, and it
seems to work fine, but are there any cases where doing something like
this could cause any problems?

Here's the small program I wrote to test this:

#include <stdio.h>
int main()
{
struct simplestruct
{
int i;
char str[8];
};

struct extendedstruct
{
int i;
char str[8];
int j;
};

struct simplestruct foostruct;
struct extendedstruct barstruct;

/* Populate the members of the simplestruct instance */
foostruct.i=7;
strcpy(foostruc t.str, "Test");

/* Copy the contents of the simplestruct instance to the
extendedstruct instance */
memcpy(&barstru ct, &foostruct, sizeof(foostruc t));

/* Populate remaining member of the extendedstruct instance */
barstruct.j=13;

/* Print values of members of the extendedstruct instance */
printf("i\t%d\n str\t%s\nj\t%d\ n", barstruct.i, barstruct.str,
barstruct.j);
}

Thanks in advance for any advice.
--
Karl Garrison
he********@yaho o.com

Nov 15 '05 #1
21 2442


he********@yaho o.com wrote:
struct simplestruct
{
int i;
char str[8];
};

struct extendedstruct
{
int i;
char str[8];
int j;
};


A lower maintainence, less error prone way to do this is
struct simplestruct { ... };
struct extendedstruct { struct simplestruct s; ... };

Nov 15 '05 #2
he********@yaho o.com wrote:
I want to use memcpy to copy the contents of one struct to another
which is a superset of the original struct (the second struct has extra
members at the end). I wrote a small program to test this, and it
seems to work fine, but are there any cases where doing something like
this could cause any problems?

Here's the small program I wrote to test this:

#include <stdio.h>
int main()
{
struct simplestruct
{
int i;
char str[8];
};

struct extendedstruct
{
int i;
char str[8];
int j;
};

struct simplestruct foostruct;
struct extendedstruct barstruct;

/* Populate the members of the simplestruct instance */
foostruct.i=7;
strcpy(foostruc t.str, "Test");

/* Copy the contents of the simplestruct instance to the
extendedstruct instance */
memcpy(&barstru ct, &foostruct, sizeof(foostruc t));

/* Populate remaining member of the extendedstruct instance */
barstruct.j=13;

/* Print values of members of the extendedstruct instance */
printf("i\t%d\n str\t%s\nj\t%d\ n", barstruct.i, barstruct.str,
barstruct.j);
}

Thanks in advance for any advice.


It is possible that sizeof foostruct == sizeof barstruct;
take another example:

struct simplestruct
{
int i;
char str[7];
};

struct extendedstruct
{
int i;
char str[7];
unsigned char j;
};

On typical implementations with 8bit char and 32bit or 16bit int and
minimal padding, it is now probable that sizeof foostruct == sizeof
barstruct, so your padding in simplestruct overwrites your useful
information in extendedstruct.
So, either you memcpy() (offsetof(struc t simplestruct, str) + sizeof
foostruct.str) bytes (the offsetof macro comes from <stddef.h>) or
you follow the hint given in another reply, namely
struct extendedstruct
{
struct simplestruct mySimple;
unsigned char j;
}
Then, you do not even need memcpy():
barstruct.mySim ple = foostruct;
suffices.
(In addition, you can abuse the address of barstruct as a
struct simplestruct*, if necessary -- but I have not said that ;-))
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #3
On 27 Jul 2005 12:32:08 -0700, "he********@yah oo.com"
<kg*******@pobo x.com> wrote:
I want to use memcpy to copy the contents of one struct to another
which is a superset of the original struct (the second struct has extra
members at the end). I wrote a small program to test this, and it
seems to work fine, but are there any cases where doing something like
this could cause any problems?


There is no guarantee that the padding in the common part of the two
structs is the same. It is also possible for the shorter struct to
have padding at the end but in the longer struct there could be an
actual member at the same offset.
<<Remove the del for email>>
Nov 15 '05 #4
tedu wrote:
A lower maintainence [...]


to maintain, yes, but maintenance ;-)
Nov 15 '05 #5
"he********@yah oo.com" wrote:

I want to use memcpy to copy the contents of one struct to another
which is a superset of the original struct (the second struct has
extra members at the end). I wrote a small program to test this,
and it seems to work fine, but are there any cases where doing
something like this could cause any problems?


Why do snaky things in the first place? Just write down what you
want:

struct smaller {
....
} smallguy;

struct bigger {
struct smaller small;
....
} bigguy;

....

bigguy.small = smallguy;

and I find it hard to imagine what could go wrong.

--
"If you want to post a followup via groups.google.c om, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson

Nov 15 '05 #6
CBFalconer wrote
(in article <42************ ***@yahoo.com>) :
Why do snaky things in the first place?


you are trying to implement an adder?

<duck>
--
Randy Howard (2reply remove FOOBAR)

Nov 15 '05 #7
"Barry Schwarz" <sc******@deloz .net> wrote in message
news:g7******** *************** *********@4ax.c om...
On 27 Jul 2005 12:32:08 -0700, "he********@yah oo.com" .... There is no guarantee that the padding in the common part of the two
structs is the same.


If my memory serves me, the standard gurantees that. But, I'd prefer to turn
that common part into a type used inside both structs. memcpy() will be able
to do bad things silently...

Alex
Nov 15 '05 #8
On Fri, 29 Jul 2005 00:56:03 +0400, Alexei A. Frounze wrote:
"Barry Schwarz" <sc******@deloz .net> wrote in message
news:g7******** *************** *********@4ax.c om...
On 27 Jul 2005 12:32:08 -0700, "he********@yah oo.com" ...
There is no guarantee that the padding in the common part of the two
structs is the same.


If my memory serves me, the standard gurantees that.


Perhaps you aren't using error correction on your memory. :)

Barry is right, the standard doesn't guarantee it. The alignment of
members within a struct is "implementa tion-defined" (I can't imagine why
in practice a compiler would not pad them identically, but it isn't
prohibited from padding differently).

The only guarantees about member positions in structs are that no hole
will occur at the beginning and that members will occupy increasing
storage addresses.

Padding also may be added at the end to ensure correct alignment for
arrays of the struct (but this is again at the implementation' s discretion
- i.e. not of predictable / guaranteed / repeatable size).
But, I'd prefer to turn
that common part into a type used inside both structs. memcpy() will be able
to do bad things silently...


memcpy() may do bad things if the common part is not padded identically,
as well as if the smaller struct has padding at the end in space at which
the larger struct has a member.

You're right that your preferred solution is safe though.

Nov 15 '05 #9
Netocrat <ne******@dodo. com.au> writes:
On Fri, 29 Jul 2005 00:56:03 +0400, Alexei A. Frounze wrote:
"Barry Schwarz" <sc******@deloz .net> wrote in message
news:g7******** *************** *********@4ax.c om...
On 27 Jul 2005 12:32:08 -0700, "he********@yah oo.com" ...
There is no guarantee that the padding in the common part of the two
structs is the same.


If my memory serves me, the standard gurantees that.


Perhaps you aren't using error correction on your memory. :)

Barry is right, the standard doesn't guarantee it. The alignment of
members within a struct is "implementa tion-defined" (I can't imagine why
in practice a compiler would not pad them identically, but it isn't
prohibited from padding differently).

The only guarantees about member positions in structs are that no hole
will occur at the beginning and that members will occupy increasing
storage addresses.


But there is an additional guarantee. C99 6.5.2.3p5 says:

One special guarantee is made in order to simplify the use of
unions: if a union contains several structures that share a common
initial sequence (see below), and if the union object currently
contains one of these structures, it is permitted to inspect the
common initial part of any of them anywhere that a declaration of
the complete type of the union is visible. Two structures share a
common initial sequence if corresponding members have compatible
types (and, for bit-fields, the same widths) for a sequence of one
or more initial members.

There's no explicit guarantee *unless* the two structures are members
of the same union, but it's hard to imagine an implementation other
than the DS9K meeting this requirement for union members without
meeting it for all structures with common initial sequences.
Padding also may be added at the end to ensure correct alignment for
arrays of the struct (but this is again at the implementation' s discretion
- i.e. not of predictable / guaranteed / repeatable size).
But, I'd prefer to turn
that common part into a type used inside both structs. memcpy() will be able
to do bad things silently...


memcpy() may do bad things if the common part is not padded identically,
as well as if the smaller struct has padding at the end in space at which
the larger struct has a member.


Yes, that can be a problem even given the additional guarantee above.
For example, given:

struct foo {
int x;
char y;
}

struct foobar {
int x;
char y;
char z;
}

it's effectively guaranteed that the x and y members will have the
same size and offset in both structures, but the z member of struct
foobar could very well occupy some of the padding of struct foo.
You're right that your preferred solution is safe though.


Agreed.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
2290
by: Josiah Carlson | last post by:
Good day everyone, I have produced a patch against the latest CVS to add support for two new formatting characters in the struct module. It is currently an RFE, which I include a link to at the end of this post. Please read the email before you respond to it. Generally, the struct module is for packing and unpacking of binary data. It includes support to pack and unpack the c types: byte, char, short, long, long long, char, *, and...
5
17607
by: Roy Hills | last post by:
When I'm reading from or writing to a network socket, I want to use a struct to represent the structured data, but must use an unsigned char buffer for the call to sendto() or recvfrom(). I have two questions: 1. Is it generally safe to "overlay" the structure on the buffer, e.g.: unsigned char buffer;
10
1682
by: Xavier Noria | last post by:
Given two structures of the same size but different type, does C99 guarantee that pointers to them can be casted one to each other, and that the order of the elements will be kind of respected? This code illustrates what I mean: int main(void) { struct foo { char c; }; struct bar { char c0; char c1; };
5
3279
by: Victor Bazarov | last post by:
Below you will find some code I wrote to see if I could wrap array copying (especially for multi-dimensional arrays) in a simple class and/or function. It seems to work fine for one-dimensioned arrays as well as two-dimensioned ones. I am sure three- or more-dimensioned array are just as OK here. My concern was that I couldn't use 'std::copy' to copy multi-dimensional arrays. Perhaps in the future we'll see specialisations of...
6
3857
by: Johs32 | last post by:
I have made a pcb pointer called current. I have then made another pointer (old_thread) that I initialize to point to the same area that current points to. If I make changes to current afterwards it also changes what old_thread points to. Why do old_thread change when I change current afterwards? If I make changes to current AFTER copying it to old_thread, I don't see why this affects old_thread.
23
4869
by: bwaichu | last post by:
To avoid padding in structures, where is the best place to put size_t variables? According the faq question 2.12 (http://c-faq.com/struct/padding.html), it says: "If you're worried about wasted space, you can minimize the effects of padding by ordering the members of a structure based on their base types, from largest to smallest."
10
4230
by: webfan | last post by:
In the code below, will the assignment z= y do bitwise copying? struct x { int a; int b; int c; }; main()
9
4255
by: Mr John FO Evans | last post by:
Am looking at adding structures to an embedded C emulator but am wondering what the standard is for copying structures(ie structa=structb) which contain pointers to memory and which are therefore not contiguous in memory. When such structures are copied what should C do with these elements? Or should copying be illegal in this case? John
160
5813
by: DiAvOl | last post by:
Hello everyone, Please take a look at the following code: #include <stdio.h> typedef struct person { char name; int age; } Person;
0
8439
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8094
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8305
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
5966
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5465
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3930
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2448
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1553
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1296
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.