bulk assignment to structure

  • Thread starter Brian K. Michalk
  • Start date
B

Brian K. Michalk

I know I can assign default values to a structure during
initialization, but I have a routine that accumulates a lot of floats
into an array, and then I would like to assign them to a (reference to
a) structure before exiting. I would like something analogous to
strcpy, but for structures. My example:

in file foo.h:
-----------------------------------
struct _stats {
float slope;
float mpd;
float macro_sum;
float grabf[13][6];
};
typedef struct _stats t_stats;

t_stats ts_min;



in file foo.c:
-----------------------------------
#include "foo.h"

void some_routine_to_reset_ts_min(void) {
int i;
float *p_to_ts_min;
float some_array[81]= {0.01, 0.02, 0.03 ... 0.81};

// now populate the global ts_min structure
// it would be great to have the equivalent of strcpy, like
structcpy(ts_min, some_array);

// assigning by element name is tedious and prohibits easy code
change of
// constants determined from lab results like:
ts_min.slope = 0.01; // doable but difficult to revize
constants

// is it valid to do the following?
p_to_ts_min = &ts_min;
for (i=0; i<81; i++) {
p_to_ts_min = some_array;
}
}

Is there a better way to do this?
 
K

Kris Wempa

Read about the function memcpy(). This function basicalyl copies X number
of bytes from one memory location to the other. This should help you out.

Kris
 
E

Eric Sosman

Brian K. Michalk said:
I know I can assign default values to a structure during
initialization, but I have a routine that accumulates a lot of floats
into an array, and then I would like to assign them to a (reference to
a) structure before exiting. I would like something analogous to
strcpy, but for structures. My example:

in file foo.h:
-----------------------------------
struct _stats {
float slope;
float mpd;
float macro_sum;
float grabf[13][6];
};
typedef struct _stats t_stats;

t_stats ts_min;

in file foo.c:
-----------------------------------
#include "foo.h"

void some_routine_to_reset_ts_min(void) {
int i;
float *p_to_ts_min;
float some_array[81]= {0.01, 0.02, 0.03 ... 0.81};

// now populate the global ts_min structure
// it would be great to have the equivalent of strcpy, like
structcpy(ts_min, some_array);

// assigning by element name is tedious and prohibits easy code
change of
// constants determined from lab results like:
ts_min.slope = 0.01; // doable but difficult to revize
constants

// is it valid to do the following?
p_to_ts_min = &ts_min;
for (i=0; i<81; i++) {
p_to_ts_min = some_array;
}
}


No, because there can be padding after any element in
a struct. Some of your `some_array' values may land in
those padding positions.
Is there a better way to do this?

Many. I'd suggest something like:

float *p = some_array;

ts_min.slope = *p++;
ts_min.mpd = *p++;
ts_min.macro_sum = *p++;
for (i = 0; i < 13; ++i) {
for (j = 0; j < 6; ++j)
ts_min.grabf[j] = *p++;
}

You might (or might not) feel like substituting memcpy()
for the inner loop.

A question: Is there any reason why some_array must
actually be an array? If it were an instance of a struct
_stats object (bad choice of name, by the way), you could
copy the whole business with one single assignment.
 
T

The Real OS/2 Guy

Read about the function memcpy(). This function basicalyl copies X number
of bytes from one memory location to the other. This should help you out.

No, it doesn't. An array is NOT a struct. The only you will get is
undefined behavior.

The only you may do is to define a static struct that gets initialised
with a set of default values. You can copy that struct into another my
memcpy. But copying an array into a struct would not work because a
struct may use another set of padding bits than a single variable or
an array uses. Maybe it works in your implementation now - but change
the version of your compiler or any other member of your
implementation and it fails.
 
K

Kris Wempa

I wasn't implying that it was going to solve all the issues. However, it
comes in handy in many cases and was close to what he was trying to do.
 
T

The Real OS/2 Guy

I wasn't implying that it was going to solve all the issues. However, it
comes in handy in many cases and was close to what he was trying to do.

It doesn't solve a single issue. using memcpy() for any other type
than (un)signed char is never a solution - except you use for both
bointers objects to the same type. An array is not a single object,
even as itself is a boundle of objects. A struct is not an array even
as you can make an array of struct. A float, int or struct is not an
array of bytes. You may however use a mem...() function to topy one
object of a type to another object of the same type but when you
starts to mixup the types you goes into the lands of undefined
behavior.

Undefined behvior means it can work with the current translation - but
fail with next one, another version of your compiler, another date or
only because it rains or the sun shines. It may work during debug but
will fail in production, it can do anything you expect or ever fail.
It can ever work at moday and ever fail on wednesday, it works on your
burthday but fails on any other day or reverse.

Whenever you have a problem with your data you have decided for a
wrong data layout. You should redesign your data layout. Not only when
your piece of data is object of change you should build a single
module that handles this kind. Then if the change occures rework this
module only and it's done. Make clean interfaces to it and you won.

Programming is a serie of design steps before coding:
- define the whole data layout
- test it, when test fails repeat the previous step
- define you program layout depending on the data layout
- test it, when it fails repeat the steps prior
- define clean interfaces
- test them, when failed repeat with one of the steps above
- write modular code that is able to handle the data
- test it, when failed repeat with one of the prior steps
- write modular code that makes its interaction with the souce of the
data
- test it, when failed repeat with one of the prior steps
- write modular code that makes its interaction with the destination
of the data
- test....
- write modular code that reflects the whole data flow
- test...
- write main() to bind all the modules to bind them right together
- test...
- retest....
- let the DAU test it....
release the program
wait for bug reports

You'll spend more time to get the data model working right than for
all other
You'll spend more time to get the program flow right than for coding
it
You'll spend more time for designing the user interaction than for
coding it

Whenever you starts without a clean and tested data model you'll loose
a multiple of time as when you had spent many time to get it clean
before starting to write the very first statement.

Then you would never come to the problem that you would copy an array
into a structure.
 
G

goose

Kris Wempa said:
I wasn't implying that it was going to solve all the issues. However, it
comes in handy in many cases and was close to what he was trying to do.

1. top posting in clc is generally frowned upon.
2. read the clc faq before posting again. the link to the
faq is in most of the regulars signature.

hth
goose,
no sig yet
 
B

Brian K. Michalk

Eric Sosman said:
No, because there can be padding after any element in
a struct. Some of your `some_array' values may land in
those padding positions.

Yes, I knew that, but thought some wizard might have some library that
would allow it like for initialization. I'me sure when it's
initialized, it acually happens at compile time, and that's why it
doesn't work at run time.
Many. I'd suggest something like:

float *p = some_array;

ts_min.slope = *p++;
ts_min.mpd = *p++;
ts_min.macro_sum = *p++;
for (i = 0; i < 13; ++i) {
for (j = 0; j < 6; ++j)
ts_min.grabf[j] = *p++;
}


That actually very close to what I already wrote. I was curious if
there were an easier way.
A question: Is there any reason why some_array must
actually be an array? If it were an instance of a struct
_stats object (bad choice of name, by the way), you could
copy the whole business with one single assignment.

Well, yes. I'm using an external library that is automatically
generated by some neural network software. It takes an array of
floats, but when I generate the statistics it's much easier to use the
structure.
 

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,083
Messages
2,570,591
Members
47,212
Latest member
RobynWiley

Latest Threads

Top