Copy array of structs in one go


D

dude.jimbo

I want to copy an array of structs (fixed size array and struct). What I "have" now (yes, this is indeed a non-compilable extract, and yes, "BOOL" is a big no-no, and no, I obviously don't have two globals that should contain the exact same thing):

struct arrayStruct
{
int a;
int b;
BOOL c;
}

struct arrayStruct dest[ARR_SIZE];
struct arrayStruct source[ARR_SIZE];

void SomeCode(void)
{
/* ... */
for (i=0; i<ARR_SIZE; i++)
{
dest.a = source.a;
dest.b = source.b;
dest.c = source.c;
}
}

This can't be right.

Well, that is to say, technically, it ~is~ right, but surely it can be faster
(not to mention that the real example has plenty more members in the struct).

You'd think I could do something along the lines of:

for (i=0; i<ARR_SIZE; i++)
{
dest = source;
}

Or, even better:

dest = source;

OK, OK, *you* don't think you could do that. But *I* think I should be able to
do something ~like~ that. So I tried, and obviously, it failed.

No, in reality, ~I~ failed. But my fragile ego doesn't like to see it spelled
out like that.

("*dest = *source" sort of worked, but only for the first entry in the arrays)

Can someone help me out with *working* syntax? And yes, I should hang my head in
shame. Apart from the fact that I don't normally program in C. In fact, I don't
normally program at all. Oh the joys of looking smart whilst seated in front of
a PC...

Jimbo
 
Ad

Advertisements

B

BartC

I want to copy an array of structs (fixed size array and struct). What I
"have" now (yes, this is indeed a non-compilable extract, and yes, "BOOL"
is a big no-no, and no, I obviously don't have two globals that should
contain the exact same thing):

struct arrayStruct
{
int a;
int b;
BOOL c;
}

struct arrayStruct dest[ARR_SIZE];
struct arrayStruct source[ARR_SIZE];

void SomeCode(void)
{
/* ... */
for (i=0; i<ARR_SIZE; i++)
{
dest.a = source.a;
dest.b = source.b;
dest.c = source.c;
}
}

This can't be right.

Well, that is to say, technically, it ~is~ right, but surely it can be
faster
(not to mention that the real example has plenty more members in the
struct).

You'd think I could do something along the lines of:

for (i=0; i<ARR_SIZE; i++)
{
dest = source;
}

Or, even better:

dest = source;

OK, OK, *you* don't think you could do that. But *I* think I should be
able to
do something ~like~ that. So I tried, and obviously, it failed.


Try:

memcpy(dest,source,sizeof(dest));

Note this will copy any padding too.
 
S

Stefan Ram

I want to copy an array of structs (fixed size array and struct).

#include <stdio.h> /* printf */

struct s { struct { int a; int b; }a[ 3 ]; };

int main()
{ struct s const s0 = { { { 1, 2 }, { 4, 3 }, { 9, 7 } } };
struct s s1; s1 = s0; printf( "%d (9)\n", s1.a[ 2 ].a ); }
 
D

dude.jimbo

Try:
memcpy(dest,source,sizeof(dest));
Note this will copy any padding too.

Well for <insert-entity-here> <insert-foul-language-here>!!1!!

<keep-going-for-a-while>!!!1!el3ven!

That - obviously - worked.

Of course, not only being an idiot but a stubborn know-it-all too,
I just ~had to~ change it to:

memcpy(dest, source, sizeof(struct arrayStruct));
/* (Note. The. Spaces. I'd fit right in into any dev-team; if I could develop,
* that is) */

which worked too, and looks prettier. No, really, it does. Not only because
I came up with it (*), but also because "dest" in reality looks something like
"someHorriblyNamedPointer_withRandomUnderScorezzzPtr_p->el.thisBeMember_here.OfSomethingElsE.dest",
if you catch my drift. Well, you probably *don't* catch my drift (nor do I wish
it upon you), but that's because I'm mentally defective when it comes to these
things.

In fact, I'm mentally defective about a lot of other things too, but
that's off-topic. Although my shrink does say that talking about it helps.
It doesn't, apart from the fact that he keeps being paid, so I guess he
has some sort of point. And a villa and an Aston and a mistress, but I'm
drifting off-topic again...

Also, padding is good. It must be, because they've lined my bedroom with it.

#include <stdio.h> /* printf */

struct s { struct { int a; int b; }a[ 3 ]; };

int main()
{ struct s const s0 = { { { 1, 2 }, { 4, 3 }, { 9, 7 } } };
struct s s1; s1 = s0; printf( "%d (9)\n", s1.a[ 2 ].a ); }

I tried reading that, but that had me grabbing for the Dafalgan.
I then tried to ~understand~ what you were trying to show, but that had me
grabbing for the bottle of Whisky, to swallow down even more Dafalgan. It
might have been whiskey too, but I wasn't paying attention since I was in
the process of passing out. Yes, more bills for another doctor. Who'd have
thought that working would cost so much money?

Anyway, are you saying that "dest = source" should have worked, provided
I first perform what looks like magic on the arrayStruct definition?

Not being the scary kind (thanks to medication), I tried your snippet,
which led to some explosions nearby (you weren't trying to be funny,
were you?), but beyond that s1 did indeed contain a copy of s0,
after 's1 = s0'.

So back to my code, and why it didn't work there.

Not being the lazy kind (thanks to being overlooked behind my back), I tried to
"purify" your convoluted snippet - it must be convoluted, because why else
can't I understand it? - to the following:

struct s {
int a;
int b;
};

struct s s0[3] = { { 1, 2 }, { 4, 3 }, { 9, 7 } };
struct s s1[3];

int main(void)
{
s1 = s0;
printf( "%d (9)\n", s1.a[ 2 ]);
}

which had me back to square one with "incompatible types in assignment s1=s0".

Besides which, I don't think I'm at liberty to change arrayStruct with
magic. Even if it is functional magic. A bit like Copperfield scoring that
German chick. I mean really, it can't have been his looks. But I'm
drifting again...

Agrh, so many problems, so little whisk(e)y...

Jimbo.


(*) OK, OK, I saw it in a manual.
 
D

David Brown

Note - it helps if you reply to replies, keeping sense of the threads
and branches in the conversation, rather than making one big reply with
other things mixed in. That way we can see who wrote what.

Well for <insert-entity-here> <insert-foul-language-here>!!1!!

<keep-going-for-a-while>!!!1!el3ven!

That - obviously - worked.

Of course, not only being an idiot but a stubborn know-it-all too,
I just ~had to~ change it to:

memcpy(dest, source, sizeof(struct arrayStruct));
/* (Note. The. Spaces. I'd fit right in into any dev-team; if I could develop,
* that is) */

The spacing is good (better than Bart's) - the sizeof part is not good.
This should be the size of everything you want to copy - i.e.,
sizeof(dest) or sizeof(source) - not the size of one element of the array.
which worked too, and looks prettier. No, really, it does. Not only because
I came up with it (*), but also because "dest" in reality looks something like
"someHorriblyNamedPointer_withRandomUnderScorezzzPtr_p->el.thisBeMember_here.OfSomethingElsE.dest",
if you catch my drift. Well, you probably *don't* catch my drift (nor do I wish
it upon you), but that's because I'm mentally defective when it comes to these
things.

Just remember what memcpy does. It takes two pointer parameters and a
byte count parameter, and copies from the source to the destination. If
you have complicated parameters here, be careful to get the parts correct.

memcpy may be more efficient if it knows about alignments. Standard
memcpy is byte-by-byte, which will be slow, but most toolchains can get
you a more optimised memcpy if you have enabled optimisation, built-in
functions, etc. Check this if speed is important.
In fact, I'm mentally defective about a lot of other things too, but
that's off-topic. Although my shrink does say that talking about it helps.
It doesn't, apart from the fact that he keeps being paid, so I guess he
has some sort of point. And a villa and an Aston and a mistress, but I'm
drifting off-topic again...

Also, padding is good. It must be, because they've lined my bedroom with it.

#include <stdio.h> /* printf */

struct s { struct { int a; int b; }a[ 3 ]; };

int main()
{ struct s const s0 = { { { 1, 2 }, { 4, 3 }, { 9, 7 } } };
struct s s1; s1 = s0; printf( "%d (9)\n", s1.a[ 2 ].a ); }

I tried reading that, but that had me grabbing for the Dafalgan.
I then tried to ~understand~ what you were trying to show, but that had me
grabbing for the bottle of Whisky, to swallow down even more Dafalgan. It
might have been whiskey too, but I wasn't paying attention since I was in
the process of passing out. Yes, more bills for another doctor. Who'd have
thought that working would cost so much money?

Anyway, are you saying that "dest = source" should have worked, provided
I first perform what looks like magic on the arrayStruct definition?

Basically, I think what Stefan is trying to say is that assignment
between structures is allowed. Assignment between arrays is not
allowed. So you could have written:

void SomeCode(void) {
for (int i = 0; i < ARR_SIZE; i++) {
dest = source;
}
}

This may or may not copy the padding, but it should use quite efficient
transfer sizes.
 
Ad

Advertisements

D

dude.jimbo

Op dinsdag 15 april 2014 18:07:42 UTC+2 schreef David Brown:
Note - it helps if you reply to replies, keeping sense of the threads

and branches in the conversation, rather than making one big reply with

other things mixed in. That way we can see who wrote what.

I know. No really, I do, but I'm doing this through the Google I/F.

And apparently, Google is paid per line-feed. Or something. So I tried
to somewhat fake the layout, which of course is only worse but it does
make me feel good about myself, taking it up to the Big Evil Corp.

That's my excuse anyway and I'm sticking to it.

(In reality, I also have no idea how to respond to two posts/points at once,
and multiple replies ~really~ look sloppy to me)
 
K

Keith Thompson

I want to copy an array of structs (fixed size array and struct). What
I "have" now (yes, this is indeed a non-compilable extract, and yes,
"BOOL" is a big no-no, and no, I obviously don't have two globals that
should contain the exact same thing):

Why is BOOL a "big no-no"? If your implementation supports it, it's
but if not I don't said:
struct arrayStruct
{
int a;
int b;
BOOL c;
}

struct arrayStruct dest[ARR_SIZE];
struct arrayStruct source[ARR_SIZE];

void SomeCode(void)
{
/* ... */
for (i=0; i<ARR_SIZE; i++)
{
dest.a = source.a;
dest.b = source.b;
dest.c = source.c;
}
}

This can't be right.

Well, that is to say, technically, it ~is~ right, but surely it can be faster
(not to mention that the real example has plenty more members in the struct).

You'd think I could do something along the lines of:

for (i=0; i<ARR_SIZE; i++)
{
dest = source;
}


That should work. Did you actually try it?
Or, even better:

dest = source;

Unfortunately, you can't assign arrays in C. But you can assign
structures.

But memcpy() is probably a better solution anyway.

[...]
 
K

Keith Thompson

Well for <insert-entity-here> <insert-foul-language-here>!!1!!

<keep-going-for-a-while>!!!1!el3ven!

That - obviously - worked.

Of course, not only being an idiot but a stubborn know-it-all too,
I just ~had to~ change it to:

memcpy(dest, source, sizeof(struct arrayStruct));
/* (Note. The. Spaces. I'd fit right in into any dev-team; if I could develop,
* that is) */

which worked too, and looks prettier. No, really, it does. Not only
because I came up with it (*), but also because "dest" in reality
looks something like
"someHorriblyNamedPointer_withRandomUnderScorezzzPtr_p->el.thisBeMember_here.OfSomethingElsE.dest",
[...]

The point of writing "sizeof(dest)", or "sizeof dest" (the , is that you don't
have to refer to
"someHorriblyNamedPointer_withRandomUnderScorezzzPtr_p...".

And it also has the considerable virtue of being correct. Your "struct
arrayStruct" (which isn't, and doesn't contain, an array, so you might
want to pick a better name) is a single element of your "dest" array.
If you only wanted to copy a single element, you might as well use an
assignment.

Your dest array is defined as:

struct arrayStruct dest[ARR_SIZE];

so if you insist on using a type name in your sizeof expression,
it would have to be "sizeof (struct arrayStruct[ARR_SIZE])" --
which would become invalid if you ever change the type of "dest".
Using "sizeof dest" is simpler and immune to that particular problem.

Or you could write:

memcpy(dest, source, ARR_SIZE * sizeof(struct arrayStruct));

but then you're repeating even more information that's already available
in the definition of "dest".

(And, IMHO, "sizeof dest" is prettier.)
 
D

dude.jimbo

Op dinsdag 15 april 2014 18:07:42 UTC+2 schreef David Brown:
The spacing is good (better than Bart's) - the sizeof part is not good.
This should be the size of everything you want to copy - i.e.,
sizeof(dest) or sizeof(source) - not the size of one element of the array.

You are, of course, quite right, but it was my mistake in mixing up my
dumbed down example from the top, with the actual code I was trying ~this
time round~.

And that actually looked more like (yet another dumbed down example):

struct arrayStruct
{
int a;
int b;
bool c;
}

struct arrayPlaceHolder
{
int a;
bool b;
char c[10];
struct arrayStruct arrayBeHere[ARR_SIZE];
}

struct arrayPlaceHolder dest;
struct arrayPlaceHolder source;

someCode()
{
memcpy(dest, source, sizeof(struct arrayPlaceHolder));
}

In which case the sizeof ~is~ correct. And prettier. Well, I dont know
if it really is correct, I just saw it working without explosions.

But now I hear you thinking (yes, I'm seeking professional help for the
voices in my head too):

"Ohhhhh-Kay.... but then 'dest = source' really would have worked"

And you'd be right again. But that's because I've been dumbing down
too much. Or been having too much scotch with Dafalgan. The conclusive
part of the analysis is that I was mixing two completely different pieces
of dumbed down code, leading to my above error.

Anyway, now I'm just rambling (while realising that nobody will
spot a difference with how it was before).

This is the key, in essence: """what Stefan is trying to say is that assignment
between structures is allowed. Assignment between arrays is not"""

Jimbo.
 
D

dude.jimbo

Op dinsdag 15 april 2014 18:26:02 UTC+2 schreef Keith Thompson:
Why is BOOL a "big no-no"? If your implementation supports it, it's
porbably better to use bool, defined in <stdbool.h>, but if not I don't
see a problem with BOOL (assuming it's defined properly, of course).

Of course BOOL is not really a big NO-NO (it is, in fact, a char, in my case)

But I've heard plenty of "booleans-in-C" discussions around the coffee-
machine - whilst fantasizing about poking out the eyes of the people involved
by using a rusty spoon - so I thought I'd tried to be funny.

Obviously, I'm as good at that as I am at writing C.

Jimbo
 
Ad

Advertisements

S

Sjouke Burry

I want to copy an array of structs (fixed size array and struct). What I
"have" now (yes, this is indeed a non-compilable extract, and yes, "BOOL"
is a big no-no, and no, I obviously don't have two globals that should
contain the exact same thing):

struct arrayStruct
{
int a;
int b;
BOOL c;
}

struct arrayStruct dest[ARR_SIZE];
struct arrayStruct source[ARR_SIZE];

void SomeCode(void)
{
/* ... */
for (i=0; i<ARR_SIZE; i++)
{
dest.a = source.a;
dest.b = source.b;
dest.c = source.c;
}
}

This can't be right.

Well, that is to say, technically, it ~is~ right, but surely it can be
faster
(not to mention that the real example has plenty more members in the
struct).

You'd think I could do something along the lines of:

for (i=0; i<ARR_SIZE; i++)
{
dest = source;
}

Or, even better:

dest = source;

OK, OK, *you* don't think you could do that. But *I* think I should be
able to
do something ~like~ that. So I tried, and obviously, it failed.


Try:

memcpy(dest,source,sizeof(dest));

Note this will copy any padding too.

Or switch to fortran.
there you can do : dest = source
 
D

dude.jimbo

Op dinsdag 15 april 2014 19:08:31 UTC+2 schreef Sjouke Burry:
<mememe> wrote in message
I want to copy an array of structs (fixed size array and struct). What I
"have" now (yes, this is indeed a non-compilable extract, and yes, "BOOL"
is a big no-no, and no, I obviously don't have two globals that should
contain the exact same thing):

struct arrayStruct
{
int a;
int b;
BOOL c;
}

struct arrayStruct dest[ARR_SIZE];
struct arrayStruct source[ARR_SIZE];

void SomeCode(void)
{
/* ... */
for (i=0; i<ARR_SIZE; i++)
{
dest.a = source.a;
dest.b = source.b;
dest.c = source.c;
}
}

This can't be right.

Well, that is to say, technically, it ~is~ right, but surely it can be
faster
(not to mention that the real example has plenty more members in the
struct).

You'd think I could do something along the lines of:

for (i=0; i<ARR_SIZE; i++)
{
dest = source;
}

Or, even better:

dest = source;

OK, OK, *you* don't think you could do that. But *I* think I should be
able to
do something ~like~ that. So I tried, and obviously, it failed.
memcpy(dest,source,sizeof(dest));

Note this will copy any padding too.


Or switch to fortran.

there you can do : dest = source


Now ~that~ is funny!
 
G

glen herrmannsfeldt

Op dinsdag 15 april 2014 19:08:31 UTC+2 schreef Sjouke Burry:

(snip, someone wrote)
dest.a = source.a;
dest.b = source.b;
dest.c = source.c;

(snip)(snip)

(snip)
(snip)
Or switch to fortran.
there you can do : dest = source

Now ~that~ is funny!

Fortran allows array expressions, which C doesn't.

PL/I allows both array and structure expressions, or both at
the same time.

Adding array expressions to C is complicated by the way C does
pointers, but structure expressions don't have that problem.

Seems to me that one could allow:

struct somestruct a, b, c;

/* put some values in a and b */

c = a + b;

without breaking too much.


-- glen
 
S

Stefan Ram

glen herrmannsfeldt said:
Seems to me that one could allow:
struct somestruct a, b, c;
/* put some values in a and b */
c = a + b;
without breaking too much.

Welcome to the wonderful world of C++!

struct somestruct
{ somestruct & operator=( somestruct const & ){ return *this; } }
a, b, c;

somestruct operator+( somestruct & a, somestruct const & ){ return a; }

int main(){ c = a + b; }
 
G

glen herrmannsfeldt

(snip, I wrote)
Welcome to the wonderful world of C++!
struct somestruct
{ somestruct & operator=( somestruct const & ){ return *this; } }
a, b, c;
somestruct operator+( somestruct & a, somestruct const & ){ return a; }
int main(){ c = a + b; }

Some time ago, I thought about writing all such to do complex
arithmetic in C++.

Note that you also have to include the (scaler)+(struct) and
(struct)+(scalar) for all available scalar types.

You also need all operators and all library functions.

I suppose you write a program to generate them all, given the
structure of the struct in question.

DCL (x, y, z) 1 somestruct,
2 a fixed binary(31,0),
2 b fixed decimal(15,0),
2 c float binary(53),
2 d float decimal(10),
2 e char(100);

x=3;
y='4';
y=y+3.0e1;
z=x+2*y+sqrt(x-y)*sin(x/3)**'2.5';
put skip list(x, y, z);

-- glen
 
Ad

Advertisements

J

James Kuyper

Welcome to the wonderful world of C++!

struct somestruct
{ somestruct & operator=( somestruct const & ){ return *this; } }
a, b, c;

somestruct operator+( somestruct & a, somestruct const & ){ return a; }

int main(){ c = a + b; }

If you're going to bring C++ into the discussion, std::valarray<T> seems
like it would be a more relevant example.

Adding enough C++ features to make anything like that useful would erase
most of the fundamental distinctions between C and C++. Keeping things
simple is C's main advantage over C++; removing that distinction would
remove most of reasons why people still bother using C rather than C++.
 
S

Stefan Ram

James Kuyper said:
If you're going to bring C++ into the discussion, std::valarray<T> seems
like it would be a more relevant example.

»valarray« was intended for vector processors AFAIK,
but it was never really used for its intended purpose.
Possibly, because those processors are not that widely
used today.

Those who really do vector math with C++ AFAIK use
third-party libraries like »Blitz++« today.

But do not despair, help is on the way:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3851.pdf

. Disclaimer: There might not be arithmetic operators for
vectors and matrices mentioned in that draft, but this seems
to be a new attempt at multidimensional array support.
Something that also was intended for »valarray«.

I wonder if maybe one day someone will write a valarray
implementation that exploits modern graphic cards as
vector processors, but I do not know if this is possible.

C++ can copy ::std::array instances using »=«, but this is
no surprise, since in the end, AFAIK, this just wraps a C array
in a struct, so it is the same technique we also can use in C.
 
D

David Brown

Op dinsdag 15 april 2014 18:07:42 UTC+2 schreef David Brown:

I know. No really, I do, but I'm doing this through the Google I/F.

Get a real newsreader - there are plenty of good newsreader programs.
And there are plenty of free newsservers. I don't want to start a "my
newsreader is better than your newsreader" thread, but there is almost
universal agreement that Google's Usenet interface is the worst choice.
I use Thunderbird and news.external-september.org. Some people might
prefer other newsreaders and news servers, but that should get you started.
And apparently, Google is paid per line-feed. Or something. So I tried
to somewhat fake the layout, which of course is only worse but it does
make me feel good about myself, taking it up to the Big Evil Corp.

So you think Google is evil, and therefore try to use their service -
without them charging you - in such a way as to minimise /their/ income.
That's a pretty hypocritical definition of "evil". If you want to take
advantage of Google's services, you should be happy that they have an
income (within reason) so that they can give you those services.
That's my excuse anyway and I'm sticking to it.

(In reality, I also have no idea how to respond to two posts/points at once,
and multiple replies ~really~ look sloppy to me)

It doesn't matter if multiple replies "look sloppy" to you - this is
Usenet, it has its rules and conventions, and it all works far better if
people follow them. /Nothing/ looks worse than someone who thinks
/their/ way of quoting or posting is better than the method used by
everyone else.

So get yourself a real newsreader and newsserver, and when you want to
reply to a post press the "follow up" button on that post. Then we can
all go back to talking about C :)
 
Ad

Advertisements

D

David Brown

Op dinsdag 15 april 2014 18:26:02 UTC+2 schreef Keith Thompson:

Of course BOOL is not really a big NO-NO (it is, in fact, a char, in my case)

But I've heard plenty of "booleans-in-C" discussions around the coffee-
machine - whilst fantasizing about poking out the eyes of the people involved
by using a rusty spoon - so I thought I'd tried to be funny.

Obviously, I'm as good at that as I am at writing C.

Sometimes people in this group have limited auto-detect in their sense
of humour. You have to /earn/ the right to make jokes like that, by
proving over the years that you understand all the pros and cons of
different types of C booleans (and also when and how to use all-caps
identifiers). Otherwise the assumption is just that you have
misunderstood something (that is not an unreasonable assumption, of course).

Best to add a smiley to avoid confusion :)
 

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

Top