array copy via "struct-trickery"

A

anon.asdf

Hi!

OK, lets try "array-copy":

{
char arrayA[3];
arrayA = (char[]){1, 2, 3};
}
it does *not* work since we're trying to make a fixed array-pointer
arrayA, point to another location/address (where there is an
"anonymous" array holding 1, 2 and 3)



hmmm.... but have a look at this:

/*** trickery-candy ****/
#define LEN 3

struct mystruct {
char arr[LEN];
};

{
char arrayA[LEN];
char arrayB[LEN] = {1, 2, 3};
*((struct mystruct *)arrayA) = (struct mystruct){{1, 2, 3}};
*((struct mystruct *)arrayA) = *((struct mystruct *)arrayB);
}
/***************/

->it works! Using no memcpy (from string.h) or any other "normal
method"!!

Would the code for this be very similar to
memcpy(arrayA, arrayB, sizeof(arrayA));
??? (How does it compare?)

(Any other ways of doing this?)

Regards -Albert
 
B

Ben Pfaff

#define LEN 3

struct mystruct {
char arr[LEN];
};

{
char arrayA[LEN];
char arrayB[LEN] = {1, 2, 3};
*((struct mystruct *)arrayA) = (struct mystruct){{1, 2, 3}};
*((struct mystruct *)arrayA) = *((struct mystruct *)arrayB);
}

I'd recommend not doing that. For one thing, the compiler is
allowed to insert padding at the end of 'struct mystruct', so
that the structure assignment will actually write beyond the end
of the array. For another, even in the absence of trailing
padding, I suspect that the behavior is undefined given C's
aliasing rules.
 
K

Keith Thompson

OK, lets try "array-copy": [snip]

hmmm.... but have a look at this:

/*** trickery-candy ****/
#define LEN 3

struct mystruct {
char arr[LEN];
};

{
char arrayA[LEN];
char arrayB[LEN] = {1, 2, 3};
*((struct mystruct *)arrayA) = (struct mystruct){{1, 2, 3}};
*((struct mystruct *)arrayA) = *((struct mystruct *)arrayB);
}
/***************/

->it works! Using no memcpy (from string.h) or any other "normal
method"!!

Sure. You can't assign arrays, but you can assign structures, even if
the structures have members that are arrays.
Would the code for this be very similar to
memcpy(arrayA, arrayB, sizeof(arrayA));
??? (How does it compare?)

There's no reason to assume that the generated code would be
different, since it's doing exactly the same thing. The struct
assignment could well be implemented as a call to memcpy() -- or the
memcpy() call could be implemented as a sequence of MOVE instructions
(or whatever your CPU provides).

I'd just use memcpy() because it's clearer.
(Any other ways of doing this?)

Undoubtedly, but how many ways do you need?
 
O

Old Wolf

{
char arrayA[LEN];
char arrayB[LEN] = {1, 2, 3};
*((struct mystruct *)arrayA) = (struct mystruct){{1, 2, 3}};
*((struct mystruct *)arrayA) = *((struct mystruct *)arrayB);
}

I'd recommend not doing that. For one thing, the compiler is
allowed to insert padding at the end of 'struct mystruct', so
that the structure assignment will actually write beyond the end
of the array. For another, even in the absence of trailing
padding, I suspect that the behavior is undefined given C's
aliasing rules.

The aliasing rules allow anything to be aliased as char,
I think. However, the behaviour would be undefined if
arrayA is not correctly aligned for a struct mystruct.
 
B

Ben Pfaff

Old Wolf said:
{
char arrayA[LEN];
char arrayB[LEN] = {1, 2, 3};
*((struct mystruct *)arrayA) = (struct mystruct){{1, 2, 3}};
*((struct mystruct *)arrayA) = *((struct mystruct *)arrayB);
}

I'd recommend not doing that. For one thing, the compiler is
allowed to insert padding at the end of 'struct mystruct', so
that the structure assignment will actually write beyond the end
of the array. For another, even in the absence of trailing
padding, I suspect that the behavior is undefined given C's
aliasing rules.

The aliasing rules allow anything to be aliased as char,
I think.

Sure. I am not enough of an expert on C's aliasing rules to know
whether a struct encapsulating an array of char would follow the
same aliasing rules as an array of char. I suspect that it would
not.
However, the behaviour would be undefined if arrayA is not
correctly aligned for a struct mystruct.

That's a third reason not to do this. Thank you.
 
A

anon.asdf

However, the behaviour would be undefined if
arrayA is not correctly aligned for a struct mystruct.

Could it ever happen that arrayA is not correctly aligned with struct
mystruct, given the following:
#define LEN 3

struct mystruct {
char arr[LEN];
};

char arrayA[LEN];

Might the struct have padding? Would a union change the situation?

By the way - is a struct (or union) aligned according to its size, or
according to the largest component it contains?

Thanks -Albert
 
K

Keith Thompson

However, the behaviour would be undefined if
arrayA is not correctly aligned for a struct mystruct.

Could it ever happen that arrayA is not correctly aligned with struct
mystruct, given the following:
#define LEN 3

struct mystruct {
char arr[LEN];
};

char arrayA[LEN];

Yes. Note that compilers are likely to allocate objects on stricter
alignment boundaries than they really need to, so code that assumes
arrayA is strictly aligned may happen to work (until it breaks at the
most inconvenient possible moment).
Might the struct have padding?
Yes.

Would a union change the situation?
No.

By the way - is a struct (or union) aligned according to its size, or
according to the largest component it contains?

The alignment for a struct or union is at least the alignment for its
most strictly aligned member. It may be more strict. For any type,
the size must be a whole multiple of the alignment.

For example char always has one-byte alignment. An implementation
might require, say, 4-byte alignment for all structures. In that
case, this structure:

struct foo {
char c;
};

would have 4-byte alignment; it would therefore have to have at least
3 bytes of padding after 'c'. This is just one possibility; a
compiler is also free to set the size and alignment of 'struct foo' to
1 byte.
 
B

Barry Schwarz

However, the behaviour would be undefined if
arrayA is not correctly aligned for a struct mystruct.

Could it ever happen that arrayA is not correctly aligned with struct
mystruct, given the following:
#define LEN 3

struct mystruct {
char arr[LEN];
};

char arrayA[LEN];

Might the struct have padding? Would a union change the situation?

Yes. No, a union may also
have padding.
By the way - is a struct (or union) aligned according to its size, or
according to the largest component it contains?

A struct is aligned to insure that every member is also properly
aligned.

Since all the members of a union overlap, it is aligned according the
strictest alignment of its members.


Remove del for email
 
K

Keith Thompson

Barry Schwarz said:
A struct is aligned to insure that every member is also properly
aligned.

At least.
Since all the members of a union overlap, it is aligned according the
strictest alignment of its members.

At least.

A struct or union may be more strictly aligned than any of its
members. For example, an implementation might choose to give all
structs and union 4-byte alignment, even if they contain only
character members.
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top