Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Array assignment via struct (http://www.velocityreviews.com/forums/t438984-array-assignment-via-struct.html)

Eric Laberge 08-04-2005 10:41 PM

Array assignment via struct
 
Hi!

I'm working on automatically generated code, and need to assign arrays.
memcpy is an obvious solution, but it becomes complicated to use in the
context I'm working on, ie.: I could use it but I don't want to.
Arrays cannot be assigned in C, but structs can, so I coded the
following:

#include <stdlib.h>

int main(void)
{
void* a = malloc(10); /* This obviously should be checked for malloc
failure */
void* b = malloc(10); /* This too... */

*((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);

free(a);
free(b);
return 0;
}

I wouldn't have tought that this would compile, let alone not give a
single warning (gcc -W -Wall -pedantic). It even works :-), as I tried
copying and displaying a string. I can easily code that in my code
generator (a translator, actually) and I suppose it would even let me
cast expressions to an array!

What I'm wondering, since this is not too bad looking as a solution,
is:
1) Is this solution common?
2) Is this portable?
3) Does this actually respects the C standard? (if not, why?)
4) Any way to improve this assign without using a function?

FYI, I tried using anonymous structures:
*((struct {unsigned char t[10];}*) a) = *((struct {unsigned char
t[10];}*) b);
but the compiler complained about incompatible types, which I
understand the cause. I had to try it, though.

Thanks
--
Eric Laberge


Anonymous 7843 08-05-2005 01:17 AM

Re: Array assignment via struct
 
In article <1123195269.943605.38490@g47g2000cwa.googlegroups. com>,
Eric Laberge <demon_lord@myrealbox.com> wrote:
>
> *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);
>
> What I'm wondering, since this is not too bad looking as a solution,
> is:
> 1) Is this solution common?


Casting void pointers to struct pointers is *very* common indeed; however,
declaring a new struct in the middle of a statement...that part is unusual.

> 2) Is this portable?


I think so. I tried it on three completely independent
compilers and they all accepted it in c89 and c99 modes.

> 3) Does this actually respects the C standard? (if not, why?)


Dunno. Hopefully someone more fluent with the standard(s) can
indicate whether it is conforming and to what level (and
restore my confidence in my three favorite compilers!).

> 4) Any way to improve this assign without using a function?


The last time I had to move small chunks of data of size unknown-by-me
but knowable-by-the-program, I had a menu of different ways to handle it:

* Small items of 1, 2, 4, or 8 bytes were cast to built-in types of
the appropriate size (e.g. char thru double).
* Odd sized things, misaligned data, and larger objects were just passed
to memcpy().
* Overlapping data of course gets memmove().

Doing a struct copy in the source code might map to a memcpy (or worse,
memmove) in the binary anyway. You'll have to examine the assembly
output and maybe even profile the code to get a handle on what's
optimal (which seems to be the subtext of your wanting to avoid
memcpy).

Declaring a struct in the middle of doing something else is
at least visually jarring. I'd probably move the struct
declaration up and out, or at least replace the statement
in place with

do {
struct copy {unsigned char t[10];};
*((struct copy *) a) = *((struct copy*) b);
} while (0)

and maybe skip the do while(0) stuff it's straight-line generated
code, but assign unique names to the structs.
--
7842++

pete 08-05-2005 02:18 AM

Re: Array assignment via struct
 
Netocrat wrote:
>
> On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:
>
> > I'm working on automatically generated code,
> > and need to assign arrays.
> > memcpy is an obvious solution,
> > but it becomes complicated to use in the
> > context I'm working on, ie.: I could use it but I don't want to.
> > Arrays cannot be assigned in C, but structs can, so I coded the
> > following:
> >
> > #include <stdlib.h>
> >
> > int main(void)
> > {
> > void* a = malloc(10);
> > /* This obviously should be checked for malloc
> > failure */
> > void* b = malloc(10); /* This too... */
> >
> > *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);
> >
> > free(a);
> > free(b);
> > return 0;
> > }

>
> <snip>
>
> The only problem I can see is that the structure is not necessarily
> the same size as the array
> - the compiler is free to add padding to the structure.
>
> Better to declare the structure first and do sizeof on it to check.


Use sizeof structure for the argument in the call to malloc.

/* BEGIN new.c */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

struct copy {
unsigned char t[10];
};

int main(void)
{
void *a = malloc(sizeof(struct copy));
void *b = malloc(sizeof(struct copy));

if (a == NULL || b == NULL) {
puts("malloc problem");
exit(EXIT_FAILURE);
}
strcpy(b, "123456789");
*(struct copy *)a = *(struct copy *)b;
free(b);
puts(a);
free(a);
return 0;
}

/* END new.c */


--
pete

Netocrat 08-05-2005 02:55 AM

Re: Array assignment via struct
 
On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:

> I'm working on automatically generated code, and need to assign arrays.
> memcpy is an obvious solution, but it becomes complicated to use in the
> context I'm working on, ie.: I could use it but I don't want to.
> Arrays cannot be assigned in C, but structs can, so I coded the
> following:
>
> #include <stdlib.h>
>
> int main(void)
> {
> void* a = malloc(10); /* This obviously should be checked for malloc
> failure */
> void* b = malloc(10); /* This too... */
>
> *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);
>
> free(a);
> free(b);
> return 0;
> }


<snip>

The only problem I can see is that the structure is not necessarily
the same size as the array - the compiler is free to add padding to the
structure.

Better to declare the structure first and do sizeof on it to check.

Not really portable because on different platforms different amounts of
padding may be added. Memcpy is probably simpler.


Netocrat 08-05-2005 03:37 AM

Re: Array assignment via struct
 
On Fri, 05 Aug 2005 02:18:18 +0000, pete wrote:

> Netocrat wrote:
>>
>> On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:
>>
>> > I'm working on automatically generated code,
>> > and need to assign arrays.
>> > memcpy is an obvious solution,
>> > but it becomes complicated to use in the
>> > context I'm working on, ie.: I could use it but I don't want to.
>> > Arrays cannot be assigned in C, but structs can, so I coded the
>> > following:
>> >
>> > #include <stdlib.h>
>> >
>> > int main(void)
>> > {
>> > void* a = malloc(10);
>> > /* This obviously should be checked for malloc
>> > failure */
>> > void* b = malloc(10); /* This too... */
>> >
>> > *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);
>> >
>> > free(a);
>> > free(b);
>> > return 0;
>> > }

>>
>> <snip>
>>
>> The only problem I can see is that the structure is not necessarily
>> the same size as the array
>> - the compiler is free to add padding to the structure.
>>
>> Better to declare the structure first and do sizeof on it to check.

>
> Use sizeof structure for the argument in the call to malloc.



Additions untested; for comment value only...

> /* BEGIN new.c */
>
> #include <stdlib.h>
> #include <string.h>
> #include <stdio.h>


#define ARRSIZE 10

> struct copy {
> unsigned char t[ARRSIZE];
> };
>
> int main(void)
> {

void *a, b;

if (sizeof(struct copy) > ARRSIZE) {
/* do you want to have to potentially deal with this
* complication? Is it even an issue? */
}
a = malloc(sizeof(struct copy));
b = malloc(sizeof(struct copy));

>
> if (a == NULL || b == NULL) {
> puts("malloc problem");
> exit(EXIT_FAILURE);
> }
> strcpy(b, "123456789");
> *(struct copy *)a = *(struct copy *)b; free(b); puts(a); free(a);
> return 0;
> }
> }
> /* END new.c */




Suman 08-05-2005 04:34 AM

Re: Array assignment via struct
 

Netocrat wrote:
> On Fri, 05 Aug 2005 02:18:18 +0000, pete wrote:
>
> > Netocrat wrote:
> >>
> >> On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:
> >>
> >> > I'm working on automatically generated code,
> >> > and need to assign arrays.
> >> > memcpy is an obvious solution,
> >> > but it becomes complicated to use in the
> >> > context I'm working on, ie.: I could use it but I don't want to.
> >> > Arrays cannot be assigned in C, but structs can, so I coded the
> >> > following:
> >> >
> >> > #include <stdlib.h>
> >> >
> >> > int main(void)
> >> > {
> >> > void* a = malloc(10);
> >> > /* This obviously should be checked for malloc
> >> > failure */
> >> > void* b = malloc(10); /* This too... */
> >> >
> >> > *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);
> >> >
> >> > free(a);
> >> > free(b);
> >> > return 0;
> >> > }
> >>
> >> <snip>
> >>
> >> The only problem I can see is that the structure is not necessarily
> >> the same size as the array
> >> - the compiler is free to add padding to the structure.
> >>
> >> Better to declare the structure first and do sizeof on it to check.

> >
> > Use sizeof structure for the argument in the call to malloc.

>
>
> Additions untested; for comment value only...
>
> > /* BEGIN new.c */
> >
> > #include <stdlib.h>
> > #include <string.h>
> > #include <stdio.h>

>
> #define ARRSIZE 10
>
> > struct copy {
> > unsigned char t[ARRSIZE];
> > };
> >
> > int main(void)
> > {

> void *a, b;


Is this really what you want? Typo, I presume. So, we'll change it
to...
void *a, *b;
and the rest follows.

> if (sizeof(struct copy) > ARRSIZE) {
> /* do you want to have to potentially deal with this
> * complication? Is it even an issue? */
> }
> a = malloc(sizeof(struct copy));
> b = malloc(sizeof(struct copy));
>
> >
> > if (a == NULL || b == NULL) {
> > puts("malloc problem");
> > exit(EXIT_FAILURE);
> > }
> > strcpy(b, "123456789");
> > *(struct copy *)a = *(struct copy *)b; free(b); puts(a); free(a);
> > return 0;
> > }
> > }
> > /* END new.c */



Netocrat 08-05-2005 05:58 AM

Re: Array assignment via struct
 
On Thu, 04 Aug 2005 21:34:47 -0700, Suman wrote:
> Netocrat wrote:
>> On Fri, 05 Aug 2005 02:18:18 +0000, pete wrote:

<snip>
>> > int main(void)
>> > {

>> void *a, b;

>
> Is this really what you want? Typo, I presume. So, we'll change it
> to...
> void *a, *b;


Yep, typo, well caught.


Lawrence Kirby 08-05-2005 12:50 PM

Re: Array assignment via struct
 
On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:

> Hi!
>
> I'm working on automatically generated code, and need to assign arrays.
> memcpy is an obvious solution, but it becomes complicated to use in the
> context I'm working on, ie.: I could use it but I don't want to.


It is difficult to see how it would be more complicated than what you have
here.

> Arrays cannot be assigned in C, but structs can, so I coded the
> following:
>
> #include <stdlib.h>
>
> int main(void)
> {
> void* a = malloc(10); /* This obviously should be checked for malloc
> failure */
> void* b = malloc(10); /* This too... */
>
> *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);


memcpy(a, b, 10);

> free(a);
> free(b);
> return 0;
> }
>
> I wouldn't have tought that this would compile, let alone not give a
> single warning (gcc -W -Wall -pedantic). It even works :-), as I tried
> copying and displaying a string. I can easily code that in my code
> generator (a translator, actually) and I suppose it would even let me
> cast expressions to an array!


You can't cast to an array type.

> What I'm wondering, since this is not too bad looking as a solution,
> is:
> 1) Is this solution common?


Not in my experience. :-)

> 2) Is this portable?


It probably works on a wide range of implementations.

> 3) Does this actually respects the C standard? (if not, why?)


You're trying to access an array as a structure which ultimately has
undefined behaviour. The fact that malloc'd memory is used muddies the
water a bit especially in C90. But C99's concept of effective type makes
it clearer.

> 4) Any way to improve this assign without using a function?
>
> FYI, I tried using anonymous structures:
> *((struct {unsigned char t[10];}*) a) = *((struct {unsigned char
> t[10];}*) b);
> but the compiler complained about incompatible types, which I
> understand the cause. I had to try it, though.


What's the problem with using memcpy()?

Lawrence

Joe Wright 08-05-2005 08:24 PM

Re: Array assignment via struct
 
Lawrence Kirby wrote:
> On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:
>
>
>>Hi!
>>
>>I'm working on automatically generated code, and need to assign arrays.
>>memcpy is an obvious solution, but it becomes complicated to use in the
>>context I'm working on, ie.: I could use it but I don't want to.

>
>
> It is difficult to see how it would be more complicated than what you have
> here.
>
>
>>Arrays cannot be assigned in C, but structs can, so I coded the
>>following:
>>
>>#include <stdlib.h>
>>
>>int main(void)
>>{
>> void* a = malloc(10); /* This obviously should be checked for malloc
>>failure */
>> void* b = malloc(10); /* This too... */
>>
>> *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);

>
>
> memcpy(a, b, 10);
>
>
>> free(a);
>> free(b);
>> return 0;
>>}
>>
>>I wouldn't have tought that this would compile, let alone not give a
>>single warning (gcc -W -Wall -pedantic). It even works :-), as I tried
>>copying and displaying a string. I can easily code that in my code
>>generator (a translator, actually) and I suppose it would even let me
>>cast expressions to an array!

>
>
> You can't cast to an array type.
>
>
>>What I'm wondering, since this is not too bad looking as a solution,
>>is:
>>1) Is this solution common?

>
>
> Not in my experience. :-)
>
>
>>2) Is this portable?

>
>
> It probably works on a wide range of implementations.
>
>
>>3) Does this actually respects the C standard? (if not, why?)

>
>
> You're trying to access an array as a structure which ultimately has
> undefined behaviour. The fact that malloc'd memory is used muddies the
> water a bit especially in C90. But C99's concept of effective type makes
> it clearer.
>
>
>>4) Any way to improve this assign without using a function?
>>
>>FYI, I tried using anonymous structures:
>>*((struct {unsigned char t[10];}*) a) = *((struct {unsigned char
>>t[10];}*) b);
>>but the compiler complained about incompatible types, which I
>>understand the cause. I had to try it, though.

>
>
> What's the problem with using memcpy()?
>
> Lawrence

/* Assign array via struct */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define LEN 20

typedef struct {
char a[LEN];
} S;

int main(void) {
S sa;
char A[LEN];

S *ps = malloc(LEN);
char *pa = malloc(LEN);

strcpy(sa.a, "Joe Wright Rocks");
puts(sa.a);

*(S*)A = sa;
puts(A);

strcpy(ps->a, A);
puts(ps->a);

*(S*)pa = *ps;
puts(pa);

return 0;
}

I love this language. :-)

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Jack Klein 08-06-2005 03:17 AM

Re: Array assignment via struct
 
On Fri, 05 Aug 2005 16:24:25 -0400, Joe Wright <jwright@comcast.net>
wrote in comp.lang.c:

> Lawrence Kirby wrote:
> > On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:
> >
> >
> >>Hi!
> >>
> >>I'm working on automatically generated code, and need to assign arrays.
> >>memcpy is an obvious solution, but it becomes complicated to use in the
> >>context I'm working on, ie.: I could use it but I don't want to.

> >
> >
> > It is difficult to see how it would be more complicated than what you have
> > here.
> >
> >
> >>Arrays cannot be assigned in C, but structs can, so I coded the
> >>following:
> >>
> >>#include <stdlib.h>
> >>
> >>int main(void)
> >>{
> >> void* a = malloc(10); /* This obviously should be checked for malloc
> >>failure */
> >> void* b = malloc(10); /* This too... */
> >>
> >> *((struct copy {unsigned char t[10];}*) a) = *((struct copy*) b);

> >
> >
> > memcpy(a, b, 10);
> >
> >
> >> free(a);
> >> free(b);
> >> return 0;
> >>}
> >>
> >>I wouldn't have tought that this would compile, let alone not give a
> >>single warning (gcc -W -Wall -pedantic). It even works :-), as I tried
> >>copying and displaying a string. I can easily code that in my code
> >>generator (a translator, actually) and I suppose it would even let me
> >>cast expressions to an array!

> >
> >
> > You can't cast to an array type.
> >
> >
> >>What I'm wondering, since this is not too bad looking as a solution,
> >>is:
> >>1) Is this solution common?

> >
> >
> > Not in my experience. :-)
> >
> >
> >>2) Is this portable?

> >
> >
> > It probably works on a wide range of implementations.
> >
> >
> >>3) Does this actually respects the C standard? (if not, why?)

> >
> >
> > You're trying to access an array as a structure which ultimately has
> > undefined behaviour. The fact that malloc'd memory is used muddies the
> > water a bit especially in C90. But C99's concept of effective type makes
> > it clearer.
> >
> >
> >>4) Any way to improve this assign without using a function?
> >>
> >>FYI, I tried using anonymous structures:
> >>*((struct {unsigned char t[10];}*) a) = *((struct {unsigned char
> >>t[10];}*) b);
> >>but the compiler complained about incompatible types, which I
> >>understand the cause. I had to try it, though.

> >
> >
> > What's the problem with using memcpy()?
> >
> > Lawrence

> /* Assign array via struct */
>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
>
> #define LEN 20
>
> typedef struct {
> char a[LEN];
> } S;
>
> int main(void) {
> S sa;
> char A[LEN];
>
> S *ps = malloc(LEN);
> char *pa = malloc(LEN);
>
> strcpy(sa.a, "Joe Wright Rocks");
> puts(sa.a);
>
> *(S*)A = sa;


Here is where you invoke undefined behavior, since A isn't dynamically
allocated. There is no guarantee that A meets the alignment
requirements for an S. The compiler might generate code that assumes
that A is, causing some sort of trap on some platforms, or possible
misaligned data or overwriting the destination array.

> puts(A);
>
> strcpy(ps->a, A);
> puts(ps->a);
>
> *(S*)pa = *ps;
> puts(pa);
>
> return 0;
> }
>
> I love this language. :-)


I strongly dislike people who write code like this. Especially if I
have to clean up after the 'clever' programmer. It would never pass a
code inspection at any shop with decent standards. Shops that don't
do code inspections don't have decent standards by definition.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html


All times are GMT. The time now is 04:27 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.