Alignment in structure

Discussion in 'C Programming' started by MeJohn, Sep 1, 2005.

  1. MeJohn

    MeJohn Guest

    Hello,

    I have a question about the layout of the fields in a structure. I have
    read
    in a paper that if two structures contain an initial sequence of
    fields,
    all of which have compatible types, then the offsets of the
    corresponding
    fields in initial sequence are guaranteed to be the same. For example,
    with

    typedef struct {
    int a;
    int b;
    char c;
    } s1;

    typedef struct {
    int a;
    int b;
    int d[2];
    } s2;

    s1 t1;
    s2 t2;

    then the fields t1.b and t2.b have the same offset. I know that,
    according
    to the ISO specification (ISO/IEC 9899:1999, §6.5.2.3), this happens
    when
    we consider two elements of type s1 and s2 in a union, for example :

    union {
    s1 t1;
    s2 t2
    } a;

    Is it true when t1 and t2 are not fields of a union ?

    Thanks !

    Regards.

    Xavier
     
    MeJohn, Sep 1, 2005
    #1
    1. Advertising

  2. MeJohn

    Eric Sosman Guest

    MeJohn wrote:

    > Hello,
    >
    > I have a question about the layout of the fields in a structure. I have
    > read
    > in a paper that if two structures contain an initial sequence of
    > fields,
    > all of which have compatible types, then the offsets of the
    > corresponding
    > fields in initial sequence are guaranteed to be the same. For example,
    > with
    >
    > typedef struct {
    > int a;
    > int b;
    > char c;
    > } s1;
    >
    > typedef struct {
    > int a;
    > int b;
    > int d[2];
    > } s2;
    >
    > s1 t1;
    > s2 t2;
    >
    > then the fields t1.b and t2.b have the same offset. I know that,
    > according
    > to the ISO specification (ISO/IEC 9899:1999, §6.5.2.3), this happens
    > when
    > we consider two elements of type s1 and s2 in a union, for example :
    >
    > union {
    > s1 t1;
    > s2 t2
    > } a;
    >
    > Is it true when t1 and t2 are not fields of a union ?


    The special guarantee of 6.5.2.3 only applies to structs
    that are members of the same union. However, a compiler would
    need to be unbelievably perverse to let union membership (sings:
    "Look for the union label ...") change the struct layout. Even
    in the absence of your `union ... a', it would be hard for the
    compiler to prove to itself that s1 and s2 don't appear as union
    members in another source file, perhaps in a source file that
    hasn't even been written yet.

    Even if the layout of the initial struct members is the same,
    though, you're not out of the woods. Let's take a different pair
    of struct types to make the matter clearer:

    typedef struct {
    char a;
    char b;
    char c;
    } s3;

    typedef struct {
    char a;
    char b;
    double d;
    } s4;

    Now, we know from the language definition that offsetof(s3,a)
    and offsetof(s4,a) are both zero. We're also going to suppose
    that offsetof(s3,b) == offsetof(s4,b), even though this isn't
    truly guaranteed. However, this does not mean that we can
    use an s4* to access the a and b elements of an s3! The two
    struct types may well have different alignment requirements,
    and the compiler is entitled to assume that a valid s4* points
    to a location that meets the alignment requirement for an
    actual s4 instance. It might then generate different code to
    access the more stringently-aligned data: "Instead of fetching
    the two bytes individually, I'll use this clever longword-
    aligned instruction to fetch them both at one blow and then
    use fast register-to-register instructions to split 'em apart."
    If instead you point your s4* at what is actually an s3 instance
    that might not be s4-aligned, the s4-dependent generated code
    may malfunction.

    (By the way, the above is not a merely theoretical concern:
    I once tracked down a bug that stemmed from exactly this cause.)

    Advice: Avoid the practice if you can reasonably do so.
    You usually can, perhaps at the expense of introducing another
    level of struct, as in

    typedef struct { char a, b; } preamble;

    typedef struct {
    preamble p;
    char c;
    } s5;

    typedef struct {
    preamble p;
    double d;
    } s6;

    You can now take an s5* or s6*, convert it to a preamble*, and
    use the latter to access the a and b members with complete
    safety. (You must actually do the conversion, though: for the
    alignment reasons mentioned above, it would not be safe to use
    the s6* itself to access the p.a and p.b members of an s5, or
    vice versa.)

    --
    Eric Sosman
    lid
     
    Eric Sosman, Sep 1, 2005
    #2
    1. Advertising

  3. MeJohn

    MeJohn Guest

    Thank you for you answer.

    To sum up, if you consider two pointers p1 and p2 of type s1* and s2*
    respectively, the cast p1 = (s1*) p2 is safe if and only if s1 is a
    "prefix" of s2 (modulo the compatibility of the types of the fields).
     
    MeJohn, Sep 1, 2005
    #3
  4. MeJohn

    Eric Sosman Guest

    MeJohn wrote:
    > Thank you for you answer.
    >
    > To sum up, if you consider two pointers p1 and p2 of type s1* and s2*
    > respectively, the cast p1 = (s1*) p2 is safe if and only if s1 is a
    > "prefix" of s2 (modulo the compatibility of the types of the fields).


    No; I wrote that the conversion is *not* safe because
    s1 and s2 may have different alignment requirements. (Also,
    we're not talking about the entirety of s1 being a prefix of
    s2, but of the two struct types sharing a common prefix
    which might not encompass all of either type.)

    --
     
    Eric Sosman, Sep 1, 2005
    #4
  5. MeJohn wrote on 01/09/05 :
    > I have a question about the layout of the fields in a structure.


    You should not. The layout is poorly define in C. What is defined is

    - The first field has the same address than the structure.
    - The order of the fields is the same than the definition.

    The rest depends on the implementation (size, gaps...). In other words
    don't rely on it. Never.

    > I have
    > read
    > in a paper that if two structures contain an initial sequence of
    > fields,
    > all of which have compatible types, then the offsets of the
    > corresponding
    > fields in initial sequence are guaranteed to be the same. For example,
    > with


    Only the first element.

    > typedef struct {
    > int a;
    > int b;
    > char c;
    > } s1;
    >
    > typedef struct {
    > int a;
    > int b;
    > int d[2];
    > } s2;
    >
    > s1 t1;
    > s2 t2;


    here, t1.a and t2.a are 'compatible'. For the other fields, there is no
    guarantee.

    > then the fields t1.b and t2.b have the same offset. I know that,
    > according
    > to the ISO specification (ISO/IEC 9899:1999, §6.5.2.3), this happens
    > when
    > we consider two elements of type s1 and s2 in a union, for example :
    >
    > union {
    > s1 t1;
    > s2 t2
    > } a;
    >
    > Is it true when t1 and t2 are not fields of a union ?


    Same issue. Only the offsets of the first elements are guaranteed to be
    0.

    --
    Emmanuel
    The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
    The C-library: http://www.dinkumware.com/refxc.html

    "There are 10 types of people in the world today;
    those that understand binary, and those that dont."
     
    Emmanuel Delahaye, Sep 1, 2005
    #5
  6. MeJohn

    MeJohn Guest

    Do you have an example that doesn't use any pragma, or any other
    instruction to the compiler relative to the alignments ? Thanks a lot !
     
    MeJohn, Sep 2, 2005
    #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. pt
    Replies:
    4
    Views:
    349
    Hallvard B Furuseth
    Aug 1, 2006
  2. nm
    Replies:
    1
    Views:
    368
    Victor Bazarov
    May 4, 2006
  3. pt
    Replies:
    5
    Views:
    401
    Hallvard B Furuseth
    Aug 1, 2006
  4. structure alignment rules

    , May 24, 2007, in forum: C Programming
    Replies:
    4
    Views:
    372
    Kenneth Brody
    May 24, 2007
  5. xmllmx
    Replies:
    5
    Views:
    604
    Gianni Mariani
    Aug 26, 2007
Loading...

Share This Page