Memory layout question

Discussion in 'C Programming' started by achrist@easystreet.com, Nov 19, 2003.

  1. Guest

    Here's a program:


    #include <stdio.h>
    int main(int argc, char **argv)
    {
    double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
    typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
    typedef a_type *a_type_ptr;
    a_type_ptr s_ptr;
    s_ptr = (a_type_ptr) an_array;
    printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
    s_ptr -> v0,
    s_ptr -> v1,
    s_ptr -> v2,
    s_ptr -> v3,
    s_ptr -> v4 );
    }

    Using a recent gcc, this prints out the elements of the array
    correctly, i.e.

    0.00000 1.00000 2.00000 3.00000 4.00000

    For what versions (if any) of standard C is this kluge required to
    work? (same alignment and offsets for array items and struct members of
    the same type).

    TIA


    Al
     
    , Nov 19, 2003
    #1
    1. Advertising

  2. Jack Klein Guest

    On Tue, 18 Nov 2003 18:34:36 -0800, wrote in
    comp.lang.c:

    > Here's a program:
    >
    >
    > #include <stdio.h>
    > int main(int argc, char **argv)
    > {
    > double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
    > typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
    > typedef a_type *a_type_ptr;
    > a_type_ptr s_ptr;
    > s_ptr = (a_type_ptr) an_array;
    > printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
    > s_ptr -> v0,
    > s_ptr -> v1,
    > s_ptr -> v2,
    > s_ptr -> v3,
    > s_ptr -> v4 );
    > }
    >
    > Using a recent gcc, this prints out the elements of the array
    > correctly, i.e.
    >
    > 0.00000 1.00000 2.00000 3.00000 4.00000
    >
    > For what versions (if any) of standard C is this kluge required to
    > work? (same alignment and offsets for array items and struct members of
    > the same type).
    >
    > TIA
    >
    >
    > Al


    "required to work"? Absolutely none.

    --
    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++ ftp://snurse-l.org/pub/acllc-c /faq
     
    Jack Klein, Nov 19, 2003
    #2
    1. Advertising

  3. Derk Gwen Guest

    wrote:
    # Here's a program:
    #
    #
    # #include <stdio.h>
    # int main(int argc, char **argv)
    # {
    # double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
    # typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
    # typedef a_type *a_type_ptr;
    # a_type_ptr s_ptr;
    # s_ptr = (a_type_ptr) an_array;
    # printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
    # s_ptr -> v0,
    # s_ptr -> v1,
    # s_ptr -> v2,
    # s_ptr -> v3,
    # s_ptr -> v4 );
    # }
    #
    # Using a recent gcc, this prints out the elements of the array
    # correctly, i.e.
    #
    # 0.00000 1.00000 2.00000 3.00000 4.00000
    #
    # For what versions (if any) of standard C is this kluge required to
    # work? (same alignment and offsets for array items and struct members of
    # the same type).

    Potentially, every single one. The only safe standard way is to pack and
    unpack the struct element by element. If you don't want to do that, you
    can restrict your concern to just those machines this works on (practically
    all of them) and include a dynamic test in the code start up to verify
    your assumption.

    --
    Derk Gwen http://derkgwen.250free.com/html/index.html
    Who's leading this mob?
     
    Derk Gwen, Nov 19, 2003
    #3
  4. wrote:

    > Here's a program:
    >
    >
    > #include <stdio.h>
    > int main(int argc, char **argv)
    > {
    > double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
    > typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
    > typedef a_type *a_type_ptr;
    > a_type_ptr s_ptr;
    > s_ptr = (a_type_ptr) an_array;
    > printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
    > s_ptr -> v0,
    > s_ptr -> v1,
    > s_ptr -> v2,
    > s_ptr -> v3,
    > s_ptr -> v4 );
    > }
    >
    > Using a recent gcc, this prints out the elements of the array
    > correctly, i.e.
    >
    > 0.00000 1.00000 2.00000 3.00000 4.00000
    >
    > For what versions (if any) of standard C is this kluge required to
    > work? (same alignment and offsets for array items and struct members of
    > the same type).
    >
    > TIA
    >
    >
    > Al


    In summary, you are trying to access a structure:
    struct MyStruct
    {
    double v0;
    double v1;
    /* ... */
    double v4;
    };
    as an array.

    There is what I call the Structure Size Rule for C and C++:
    "The size of a structure _may_ not be equal to the sum of
    the size of its members."
    This rule comes about because a compiler is allowed to
    add "padding" elements after each member or field of a
    structure. The compiler may want to add the padding to
    make the fields easier or more convenient for the processor
    to access.

    Let us say we have a processor that likes to retrieve
    32 bit quantities, known as a fetch. Let us also say
    that the processor has an 8-bit char, 16-bit short int
    and a 32-bit int (unsigned have the same sizes). When
    the processor needs to fetch any of these quantities,
    it fetches 32 bits at a time and discards the rest.

    Given the following structure:
    struct Example
    {
    char a;
    short int b;
    int c;
    };

    The member 'a' is 8-bits wide. The processor wants to
    fetch 32 bits. Without any padding the process will
    fetch 8 bits of 'a', 16 more bits of 'b' and finally
    8 bits of 'c'. It will discard the unused bits, which
    in this case, is no problem.

    The member 'b' is 16-bits wide, but not at the first
    fetch. The processor must fetch from the location
    of the first member, remove the extraneous bits
    then shift the remaining 16 bits to the correct
    position. If we added 24 bits (32 bits - 8 bits
    of char) of padding between 'a' and 'b', then the
    fetching of 'b' would have no extraneous bits and
    no shifting to take place -- more efficient.

    The process of adding padding space is called
    "alignment". Alignment allows processors to fetch
    data more efficiently. However, adding padding
    changes the size and layout of a structure. One
    cannot map the members of a structure to a real
    world structure because of the Structure Size Rule.

    Packed Structures
    -----------------
    Some compilers have #pragmas that allow "packing"
    of structures. The term "packing" referes to the
    elimination of padding after members. This is not
    a standard C facility. Also, many compilers may
    allow packed structures but have problems accessing
    data from them correctly.

    Converting to Structures
    ------------------------
    The best process for handling real world data structures
    is to treat them as a sequence of "bytes" and extract
    and build the data yourself. This technique also allows
    one to handle Endianism (the ordering of "bytes" for
    multi-byte units). Once the structure is filled,
    it can then be accessed without any worries. The
    opposite should be followed when creating a sequence
    of bytes from a structure.


    --
    Thomas Matthews

    C++ newsgroup welcome message:
    http://www.slack.net/~shiva/welcome.txt
    C++ Faq: http://www.parashift.com/c -faq-lite
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.raos.demon.uk/acllc-c /faq.html
    Other sites:
    http://www.josuttis.com -- C++ STL Library book
     
    Thomas Matthews, Nov 19, 2003
    #4
  5. On Tue, 18 Nov 2003 18:34:36 -0800, wrote:

    >Here's a program:
    >
    >
    > #include <stdio.h>
    > int main(int argc, char **argv)
    > {
    > double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};


    The elements of the array are guaranteed to be contiguous in memory
    (no gap between the end of an_array[0] and the beginning of
    an_array[1], etc).

    > typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;


    There is no guarantee that the members of the structure will be
    contiguous (there may be padding between v0 and v1, etc).

    > typedef a_type *a_type_ptr;
    > a_type_ptr s_ptr;
    > s_ptr = (a_type_ptr) an_array;


    There is no guarantee that the alignment of an_array will satisfy the
    alignment requirement of the structure.

    > printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
    > s_ptr -> v0,
    > s_ptr -> v1,
    > s_ptr -> v2,
    > s_ptr -> v3,
    > s_ptr -> v4 );
    > }
    >
    >Using a recent gcc, this prints out the elements of the array
    >correctly, i.e.
    >
    > 0.00000 1.00000 2.00000 3.00000 4.00000


    Pure luck (good or bad depending on your viewpoint).

    >
    >For what versions (if any) of standard C is this kluge required to
    >work? (same alignment and offsets for array items and struct members of
    >the same type).


    There are only two standards (C89 and C99). The comments above apply
    to both. The answer to your question is none.


    <<Remove the del for email>>
     
    Barry Schwarz, Nov 23, 2003
    #5
  6. in comp.lang.c i read:
    > wrote:


    ># For what versions (if any) of standard C is this kluge required to
    ># work? (same alignment and offsets for array items and struct members of
    ># the same type).
    >
    >Potentially, every single one.


    also, potentially none.

    >The only safe standard way is to pack and unpack the struct element by
    >element. If you don't want to do that, you can restrict your concern to
    >just those machines this works on (practically all of them) and include a
    >dynamic test in the code start up to verify your assumption.


    and depend on the results of undefined behavior? no thanks.

    --
    a signature
     
    those who know me have no need of my name, Nov 24, 2003
    #6
    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. Rick Spiewak
    Replies:
    3
    Views:
    3,164
    Rick Spiewak
    Aug 26, 2003
  2. RobertH
    Replies:
    1
    Views:
    730
    Steve C. Orr [MVP, MCSD]
    Nov 4, 2003
  3. NWx
    Replies:
    4
    Views:
    2,964
    Kevin Spencer
    Feb 19, 2004
  4. Eric
    Replies:
    4
    Views:
    735
    clintonG
    Dec 24, 2004
  5. Replies:
    1
    Views:
    588
    John Timney \(MVP\)
    Jun 19, 2006
Loading...

Share This Page