array copy via "struct-trickery"

Discussion in 'C Programming' started by anon.asdf@gmail.com, Aug 28, 2007.

  1. Guest

    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
    , Aug 28, 2007
    #1
    1. Advertising

  2. Ben Pfaff Guest

    writes:

    > #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.
    --
    "Your correction is 100% correct and 0% helpful. Well done!"
    --Richard Heathfield
    Ben Pfaff, Aug 28, 2007
    #2
    1. Advertising

  3. writes:
    > 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?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 28, 2007
    #3
  4. Old Wolf Guest

    On Aug 29, 8:33 am, Ben Pfaff <> wrote:
    > writes:
    > > {
    > > 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.
    Old Wolf, Aug 29, 2007
    #4
  5. Ben Pfaff Guest

    Old Wolf <> writes:

    > On Aug 29, 8:33 am, Ben Pfaff <> wrote:
    >> writes:
    >> > {
    >> > 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.
    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
    Ben Pfaff, Aug 29, 2007
    #5
  6. Guest

    On Aug 29, 2:18 am, Old Wolf <> wrote:
    <snip>
    > 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
    , Aug 29, 2007
    #6
  7. writes:
    > On Aug 29, 2:18 am, Old Wolf <> wrote:
    > <snip>
    >> 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.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 29, 2007
    #7
  8. On Wed, 29 Aug 2007 02:19:02 -0700, wrote:

    >On Aug 29, 2:18 am, Old Wolf <> wrote:
    ><snip>
    >> 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
    Barry Schwarz, Aug 31, 2007
    #8
  9. Barry Schwarz <> writes:
    [...]
    > 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.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 31, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Venkat
    Replies:
    4
    Views:
    962
    Venkat
    Dec 5, 2003
  2. Replies:
    4
    Views:
    13,394
    Old Wolf
    Aug 13, 2004
  3. Alex
    Replies:
    2
    Views:
    1,202
  4. Replies:
    26
    Views:
    2,089
    Roland Pibinger
    Sep 1, 2006
  5. Marcus
    Replies:
    25
    Views:
    1,603
    Francesco
    Aug 19, 2009
Loading...

Share This Page