Array assignment via struct

E

Eric Laberge

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
 
A

Anonymous 7843

*((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.
 
P

pete

Netocrat said:
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 */
 
N

Netocrat

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.
 
N

Netocrat

Netocrat said:
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));
 
S

Suman

Netocrat said:
Netocrat said:
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.
 
L

Lawrence Kirby

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
 
J

Joe Wright

Lawrence said:
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. :)
 
J

Jack Klein

Lawrence said:
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.
 
K

Krishanu Debnath

Jack Klein wrote:
/* 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

Even if A is dynamically allocated, e.g. variable 'pa', does standard
guarantee that A is suitably aligned for struct S?
may I have C&V for that?

Krishanu
 
K

Krishanu Debnath

Netocrat wrote:

Even if A is dynamically allocated, e.g. variable 'pa', does standard
guarantee that A is suitably aligned for struct S?

It does. From the C89 draft (ANSI numbering):

4.10.3 Memory management functions

The pointer returned [by the calloc , malloc , and realloc functions] if
the allocation succeeds is suitably aligned so that it may be assigned to
a pointer to any type of object and then used to access such an object in
the space allocated ...
may I have C&V for that?

There is no constraint violation if that's what you mean.

This is exactly I am looking for, thanks.

Krishanu
 
N

Netocrat

Jack Klein wrote:
/* 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);

It's possible, but unlikely, that sizeof(S) > LEN due to padding. Better
to use sizeof(S) than LEN.

Here you are potentially copying and assigning more than the allocated
(to src and dest) LEN bytes. A compiler might do this for performance
reasons. It's probably unlikely and a little pedantic but the point is
that what you're doing isn't guaranteed safe by the standard.

Given that element a must be located at the start of struct S, and that it
is a char array of size LEN, it's hard to see how it could be aligned
differently to the char array A of size LEN. Are you referring to this
specific case or in general? If this case, could you explain how the
standard allows the alignments to be different?
Even if A is dynamically allocated, e.g. variable 'pa', does standard
guarantee that A is suitably aligned for struct S?

It does. From the C89 draft (ANSI numbering):

4.10.3 Memory management functions

The pointer returned [by the calloc , malloc , and realloc functions] if
the allocation succeeds is suitably aligned so that it may be assigned to
a pointer to any type of object and then used to access such an object in
the space allocated ...
may I have C&V for that?

There is no constraint violation if that's what you mean.
 
J

Joe Wright

Jack said:
Lawrence said:
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.
All of S is an array of char. What alignment requirements might there be
for an S? None. Structures don't have alignment requirements, their
members do. What are the alignment requirements of a char array?
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.
You 'strongly dislike people' who try to get 'clever' with C in a
newsgroup posting? Boy, are you tough.

I thought you'd get me for not checking the malloc() returns and not
free()ing ps and pa before exit. You never know your luck.
 
J

Joe Wright

Netocrat said:
Jack Klein wrote:
/* 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);


It's possible, but unlikely, that sizeof(S) > LEN due to padding. Better
to use sizeof(S) than LEN.
What padding could there be? S is essentially a char array.
Here you are potentially copying and assigning more than the allocated
(to src and dest) LEN bytes. A compiler might do this for performance
reasons. It's probably unlikely and a little pedantic but the point is
that what you're doing isn't guaranteed safe by the standard.
You're assuming sizeof sa might be greater than LEN. Why?
Given that element a must be located at the start of struct S, and that it
is a char array of size LEN, it's hard to see how it could be aligned
differently to the char array A of size LEN. Are you referring to this
specific case or in general? If this case, could you explain how the
standard allows the alignments to be different?
Now you are on my side. Welcome home.
Even if A is dynamically allocated, e.g. variable 'pa', does standard
guarantee that A is suitably aligned for struct S?


It does. From the C89 draft (ANSI numbering):

4.10.3 Memory management functions

The pointer returned [by the calloc , malloc , and realloc functions] if
the allocation succeeds is suitably aligned so that it may be assigned to
a pointer to any type of object and then used to access such an object in
the space allocated ...

may I have C&V for that?


There is no constraint violation if that's what you mean.
 
N

Netocrat

Netocrat said:
Jack Klein wrote:
<snip>

/* 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);


It's possible, but unlikely, that sizeof(S) > LEN due to padding. Better
to use sizeof(S) than LEN.
What padding could there be? S is essentially a char array.

Yeah, that's why I called it a pedantic point later in the post. Probably
the DS9000 is the only implementation to include padding. Anyhow you lose
nothing by using sizeof(S) instead of LEN and you are assured of
compliance.
You're assuming sizeof sa might be greater than LEN. Why?

As above - padding. I wrote that it might be added for performance
reasons. I don't know if such reasons legitimately exist on a real-world
implementation (I can contrive a far-fetched hypothetical implementation
where they do), but you never know what code an optimising compiler is
going to generate.

<snip rest>
 
S

S.Tobias

Lawrence Kirby said:
On Thu, 04 Aug 2005 15:41:10 -0700, Eric Laberge wrote:
[snip]
#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;
}
[snip]
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.

Taking size and allignment issues away, I thing the array (supposing
it is an array type object already) *could* be accessed through
the struct type:

n869.txt, 6.5#7:
# [#7] An object shall have its stored value accessed only by
# an lvalue expression that has one of the following types:63)
[...]
# -- an aggregate or union type that includes one of the
# aforementioned types among its members (including,
# recursively, a member of a subaggregate or contained
# union), or
 
S

S.Tobias

Netocrat said:
Jack Klein wrote:
/* 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);

It's possible, but unlikely, that sizeof(S) > LEN due to padding. Better
to use sizeof(S) than LEN.
char *pa = malloc(LEN);

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

*(S*)A = sa; [snip]
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

Given that element a must be located at the start of struct S, and that it
is a char array of size LEN, it's hard to see how it could be aligned
differently to the char array A of size LEN. Are you referring to this
specific case or in general? If this case, could you explain how the
standard allows the alignments to be different?

Type `char' has no alignment (ie. alignment(char) == 1), of course,
but at issue is not `char', but rather `char[10]'. Long time ago
(don't ask me for details now) I read that on DEC stations character
arrays in structs could have different alignments depending on their
size, so for example `char[15]' could have different alignment than
`char[31]'. All this was for purpose of memory access speed; ordinarily
`char[ANY]' doesn't have alignment (at least when ANY is a prime number,
for others I don't know), but when in a struct, a compiler
could assume that the array is positioned at a "fast" location and
generate more optimal code. (BTW, the discussion in which I read it
was about why struct-hack didn't work.)

I think that does it for an explanation of the struct alignment and
padding (later in this thread).


[snip]
There is no constraint violation if that's what you mean.

He meant "Chapter & Verse". :-D
 
T

Tim Rentsch

Eric Laberge said:
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;
}

Perhaps it would be easier have the variables be
the assignable type to begin with:

#include <stdlib.h>

typedef struct { char v[10]; } SC_10;

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

if( !a || !b ){ ... }

sprintf( b->v, "Hi there\n" ); /* array use */

*a = *b; /* assignment use */

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

No questionable behavior, and no casting necessary.

The type could be a union rather than a struct if
the "wrapped" value needs to be accessed as some
other type(s) in addition to being accessed as a
character array or unsigned character array.

If you can, it's almost always better to write
code so it doesn't need casts -- even code that
is automatically generated.
 
T

Tim Rentsch

Joe Wright said:
All of S is an array of char. What alignment requirements
might there be for an S? None. Structures don't have
alignment requirements, their members do. What are the
alignment requirements of a char array?

Structures can have alignment requirements that
are different from those of their members, and
here's a possible reason why they would.

On platforms where a 'char *' is a different
format and/or wider than an 'int *', an
implementation might choose to make all structs
be 'int' aligned, so that structure pointers
would be easier to deal with.

So a structure holding a character array would
still need 'int' alignment, even though the
contained character array would need only 'char'
alignment.

The alignment requirement also implies a sizing
requirement, since alignment_of(T) must evenly
divide 'sizeof(T)'. That's why a struct that
holds only a character array might be bigger
than the character array it holds.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top