Alignment in structure

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • MeJohn

    #1

    Alignment in structure

    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

  • Eric Sosman

    #2
    Re: Alignment in structure

    MeJohn wrote:
    [color=blue]
    > 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 ?[/color]

    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
    esosman@acm-dot-org.invalid

    Comment

    • MeJohn

      #3
      Re: Alignment in structure

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

      Comment

      • Eric Sosman

        #4
        Re: Alignment in structure



        MeJohn wrote:[color=blue]
        > 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).[/color]

        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@sun .com

        Comment

        • Emmanuel Delahaye

          #5
          Re: Alignment in structure

          MeJohn wrote on 01/09/05 :[color=blue]
          > I have a question about the layout of the fields in a structure.[/color]

          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.
          [color=blue]
          > 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[/color]

          Only the first element.
          [color=blue]
          > typedef struct {
          > int a;
          > int b;
          > char c;
          > } s1;
          >
          > typedef struct {
          > int a;
          > int b;
          > int d[2];
          > } s2;
          >
          > s1 t1;
          > s2 t2;[/color]

          here, t1.a and t2.a are 'compatible'. For the other fields, there is no
          guarantee.
          [color=blue]
          > 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 ?[/color]

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


          Comment

          • MeJohn

            #6
            Re: Alignment in structure

            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 !

            Comment

            Working...