Structure padding.

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

    Structure padding.

    Folks,

    This structure padding issue is bothering me now, could
    not locate a satisfactory answer on clc, so here it goes...

    I have a structure, given below:
    typedef struct {
    int flag;
    char keys[3][9];
    char padding[??];
    } foo;

    I need to fill in the size of padding array here so as to
    make the entire structure size a multiple of 8. Is there
    a way in which I can calculate the padding ? This structure
    will be used on AIX 5.* and RHL.

    Thanks in advance.

    Cheers,
    Amar

    --
    If you don't want to succeed, nobody will try to stop you.
  • Arthur J. O'Dwyer

    #2
    Re: Structure padding.


    On Mon, 21 Jun 2004, Amarendra wrote:[color=blue]
    >
    > This structure padding issue is bothering me now, could
    > not locate a satisfactory answer on clc, so here it goes...
    >
    > I have a structure, given below:
    > typedef struct {
    > int flag;
    > char keys[3][9];
    > char padding[??];
    > } foo;
    >
    > I need to fill in the size of padding array here so as to
    > make the entire structure size a multiple of 8. Is there
    > a way in which I can calculate the padding ?[/color]

    Obviously not. Any compiler is perfectly capable of padding
    your structure to make it a multiple of 8 bytes, minus 1, and
    there's nothing you can do about it, from the Standard's point
    of view.
    In practice, you'll probably be able to get away with a
    system-specific solution such as

    #define PAD_EIGHT(siz) ((siz) - (siz)/8*8)
    struct half_foo {
    int flag;
    char keys[3][9];
    };
    typedef struct {
    int flag;
    char keys[3][9];
    char padding[PAD_EIGHT(sizeo f (struct half_foo))];
    } foo;

    or (even less portably but much clearer to the next guy)

    typedef struct {
    int flag;
    char keys[3][9];
    char padding[1]; /* Pad to a multiple of 8 bytes */
    } foo;

    In practice, of course, it doesn't matter at all what the size
    of your structure is: let the computer worry about it. Most
    compilers have some kind of "optimize for speed/space" flag
    that will make your code run quickly no matter what the size of
    some little structure is.

    -Arthur

    Comment

    • Jens.Toerring@physik.fu-berlin.de

      #3
      Re: Structure padding.

      Amarendra <coderaptor@gma il.com> wrote:[color=blue]
      > This structure padding issue is bothering me now, could
      > not locate a satisfactory answer on clc, so here it goes...[/color]
      [color=blue]
      > I have a structure, given below:
      > typedef struct {
      > int flag;
      > char keys[3][9];
      > char padding[??];
      > } foo;[/color]
      [color=blue]
      > I need to fill in the size of padding array here so as to
      > make the entire structure size a multiple of 8. Is there
      > a way in which I can calculate the padding ? This structure
      > will be used on AIX 5.* and RHL.[/color]

      That's something clc can't answer because there is no requirement
      on how much padding a compiler is supposed to use by the C standard.
      It obviously will differ between different architectures, but also
      compilers and maybe even different compiler versions. The first
      question that comes to mind is why you need the structures size to
      be a multiple of 8?

      <OT>
      You could write a script that writes C programs that create structures
      like the above with ever increasing lengths for the padding array and
      which then write out the sizeof the structure. The script compiles
      and runs these programs until the structures size is a multiple of 8
      and you use that length of the padding array in the real program (maybe
      by writing the value into an include file to be included by the real
      program). Shouldn't be too hard to do with a reasonably short script.
      </OT>
      Regards, Jens
      --
      \ Jens Thoms Toerring ___ Jens.Toerring@p hysik.fu-berlin.de
      \______________ ____________ http://www.toerring.de

      Comment

      • Chris Torek

        #4
        Re: Structure padding.

        In article <1d0b67f4.04062 10619.6a04b728@ posting.google. com>
        Amarendra <coderaptor@gma il.com> writes:[color=blue]
        >This structure padding issue is bothering me now, could
        >not locate a satisfactory answer on clc, so here it goes...
        >
        >I have a structure, given below:
        > typedef struct {
        > int flag;
        > char keys[3][9];
        > char padding[??];
        > } foo;
        >
        >I need to fill in the size of padding array here so as to
        >make the entire structure size a multiple of 8. Is there
        >a way in which I can calculate the padding ? ...[/color]

        The answer is no -- and yes.

        There is no way to do it "in one pass", as it were, but you can
        still do it by generating the declaration at runtime, then (after
        this runtime has finished) use that declaration at a later
        compile-time.

        This does make some assumptions, such as "a later invocation of
        the compiler will use the same layout as an earlier invocation of
        the compiler" -- which should be true unless you wait too long (so
        that the compiler has been replaced with a later version), or change
        the set of flags you pass to the compiler. It also makes the build
        process for your software (much) more complicated: instead of just
        "compile all this C code", you have to do this, in sequence:

        - compile C code to generate the structure
        - run the program, putting the struct declaration into a file for
        use in the next step
        - compile the code that uses the newly-created declaration

        It is not clear to me why you want an explicit "padding blob". In
        my experience, most people who do that are trying to make the
        internal C structure layout meet some external file format -- which
        is often a mistake, as it is sometimes quite difficult to get an
        internal data structure to match external constraints at all, and
        often quite easy to make the input and output operations translate
        between "external" and "internal" formats. The translation code
        can either assume or force 8-bit "regular bytes" (octets) using "C
        bytes" (unsigned char), which are usually exactly 8 bits, and are
        never fewer than 8 bits. The "externaliz ed" octets can be matched
        to the desired layout completely portably.
        --
        In-Real-Life: Chris Torek, Wind River Systems
        Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
        email: forget about it http://web.torek.net/torek/index.html
        Reading email is like searching for food in the garbage, thanks to spammers.

        Comment

        • Thomas Matthews

          #5
          Re: Structure padding.

          Amarendra wrote:
          [color=blue]
          > Folks,
          >
          > This structure padding issue is bothering me now, could
          > not locate a satisfactory answer on clc, so here it goes...
          >
          > I have a structure, given below:
          > typedef struct {
          > int flag;
          > char keys[3][9];
          > char padding[??];
          > } foo;
          >
          > I need to fill in the size of padding array here so as to
          > make the entire structure size a multiple of 8. Is there
          > a way in which I can calculate the padding ? This structure
          > will be used on AIX 5.* and RHL.
          >
          > Thanks in advance.
          >
          > Cheers,
          > Amar
          >
          > --
          > If you don't want to succeed, nobody will try to stop you.[/color]

          In these cases, I revert to assembly language. Many assembly
          languages provide compiler directives to align data fields
          to a given boundary. I then "export" the symbol and use
          "extern" in the C language.

          --
          Thomas Matthews

          C++ newsgroup welcome message:

          C++ Faq: http://www.parashift.com/c++-faq-lite
          C Faq: http://www.eskimo.com/~scs/c-faq/top.html
          alt.comp.lang.l earn.c-c++ faq:

          Other sites:
          http://www.josuttis.com -- C++ STL Library book

          Comment

          • Arthur J. O'Dwyer

            #6
            Re: Structure padding.


            On Mon, 21 Jun 2004 Jens.Toerring@p hysik.fu-berlin.de wrote:[color=blue]
            >
            > Amarendra <coderaptor@gma il.com> wrote:[color=green]
            > > I have a structure, given below:
            > > typedef struct {
            > > int flag;
            > > char keys[3][9];
            > > char padding[??];
            > > } foo;
            > >
            > > I need to fill in the size of padding array here so as to
            > > make the entire structure size a multiple of 8. Is there
            > > a way in which I can calculate the padding ? This structure
            > > will be used on AIX 5.* and RHL.[/color][/color]
            [color=blue]
            > <OT>
            > You could write a script that writes C programs that create structures
            > like the above with ever increasing lengths for the padding array and
            > which then write out the sizeof the structure. The script compiles
            > and runs these programs until the structures size is a multiple of 8
            > and you use that length of the padding array in the real program (maybe
            > by writing the value into an include file to be included by the real
            > program). Shouldn't be too hard to do with a reasonably short script.
            > </OT>[/color]

            Hey, good idea! :)

            #include <stdio.h>

            #define PADSIZE(n) (sizeof(struct {int flag; char keys[9][3]; \
            char pad[n];}))
            #define PADOK(n) (PADSIZE(n)%8== 0)
            #define PAD (PADOK(1)? 1: PADOK(2)? 2: PADOK(3)? 3: PADOK(4)? 4: \
            PADOK(5)? 5: PADOK(6)? 6: PADOK(7)? 7: PADOK(8)? 8: -1)

            typedef struct {
            int flag;
            char keys[9][3];
            char padding[PAD];
            } foo;

            (Naturally, the OP should not use this method. Nor should anyone else.)

            -Arthur

            Comment

            • Eric Sosman

              #7
              Re: Structure padding.

              Amarendra wrote:[color=blue]
              > Folks,
              >
              > This structure padding issue is bothering me now, could
              > not locate a satisfactory answer on clc, so here it goes...
              >
              > I have a structure, given below:
              > typedef struct {
              > int flag;
              > char keys[3][9];
              > char padding[??];
              > } foo;
              >
              > I need to fill in the size of padding array here so as to
              > make the entire structure size a multiple of 8. Is there
              > a way in which I can calculate the padding ? This structure
              > will be used on AIX 5.* and RHL.[/color]

              Others have pointed out that there's no completely
              guaranteed solution (because the compiler may add more
              padding bytes you have no control over). Others have
              also offered some non-guaranteed solutions involving
              macros and/or two passes. Here's a variation that
              might be simpler, if you can tolerate having the padding
              appear "after" the struct rather than inside it:

              typedef union { /* not struct */
              struct foo_data {
              int flag;
              char keys[3][9];
              } payload;
              char overlay[(sizeof(struct foo_data) + 7) / 8];
              } foo;

              A disadvantage is that you need to write things like
              `fooptr->payload.flag ' instead of `fooptr->flag'. And,
              of course, the compiler might still decide to make the
              union larger than you want, and this might destroy the
              multiple-of-eight size.

              --
              Eric.Sosman@sun .com

              Comment

              • Dan Pop

                #8
                Re: Structure padding.

                In <1d0b67f4.04062 10619.6a04b728@ posting.google. com> coderaptor@gmai l.com (Amarendra) writes:
                [color=blue]
                >This structure padding issue is bothering me now, could
                >not locate a satisfactory answer on clc, so here it goes...
                >
                >I have a structure, given below:
                > typedef struct {
                > int flag;
                > char keys[3][9];
                > char padding[??];
                > } foo;
                >
                >I need to fill in the size of padding array here so as to
                >make the entire structure size a multiple of 8. Is there
                >a way in which I can calculate the padding ? This structure
                >will be used on AIX 5.* and RHL.[/color]

                Yes. It's not strictly guaranteed to work (it will fail if the struct
                needs to be aligned to multiples of something greater than 8 or that is
                not a power of two) and, in theory, the compiler may add some padding of
                its own at the end, but in practice you can calculate the padding if the
                compiler is happy with the idea of the structure size being a multiple of
                8. In the worst case you may have to add 8 bytes of padding, because
                you can't have arrays of size 0. Needless to say, the padding may
                differ between implementations (but this is transparent to the source
                code).

                There is more than way of doing it, but I prefer the one that completely
                virtualises the struct definition, at the expense of declaring an
                auxiliary structure, mirroring the real one, first:

                fangorn:~/tmp 155> cat test.c
                #include <stdio.h>
                #include <assert.h>
                #include <stddef.h>

                #define ALIGN 8

                struct foo_aux {
                int flag;
                char keys[3][9];
                char padding;
                };

                struct foo {
                int flag;
                char keys[3][9];
                char padding[ALIGN - offsetof(struct foo_aux, padding) % ALIGN];
                };

                int main()
                {
                assert(offsetof (struct foo_aux, padding) == offsetof(struct foo, padding));
                assert(sizeof(s truct foo) % ALIGN == 0);
                printf("%d\n", (int)sizeof(str uct foo));
                return 0;
                }
                fangorn:~/tmp 156> gcc test.c
                fangorn:~/tmp 157> ./a.out
                32

                The catch is that both struct definitions must be kept in sync, when
                changes are made. This is actually tested by the first assert. If the
                second assert fails, there is nothing you can do: the compiler is not
                happy with a structure size that is a multiple of 8.

                There is a way to automatically keep the two structures in sync, but I'm
                not very fond of it: put the common part of the two declarations in a
                separate file and include it. Change that file when you need to modify
                the structure definition. It's a readability vs maintenability tradeoff.

                fangorn:~/tmp 166> cat struct_foo.c
                int flag;
                char keys[3][9];
                fangorn:~/tmp 167> cat test.c
                #include <stdio.h>
                #include <assert.h>
                #include <stddef.h>

                #define ALIGN 8

                struct foo_aux {
                #include "struct_foo .c"
                char padding;
                };

                struct foo {
                #include "struct_foo .c"
                char padding[ALIGN - offsetof(struct foo_aux, padding) % ALIGN];
                };

                int main()
                {
                assert(sizeof(s truct foo) % ALIGN == 0);
                printf("%d\n", (int)sizeof(str uct foo));
                return 0;
                }
                fangorn:~/tmp 168> gcc test.c
                fangorn:~/tmp 169> ./a.out
                32

                Dan
                --
                Dan Pop
                DESY Zeuthen, RZ group
                Email: Dan.Pop@ifh.de

                Comment

                • Dan Pop

                  #9
                  Re: Structure padding.

                  In <40D70CF2.90805 05@sun.com> Eric Sosman <Eric.Sosman@su n.com> writes:
                  [color=blue]
                  >Amarendra wrote:[color=green]
                  >> This structure padding issue is bothering me now, could
                  >> not locate a satisfactory answer on clc, so here it goes...
                  >>
                  >> I have a structure, given below:
                  >> typedef struct {
                  >> int flag;
                  >> char keys[3][9];
                  >> char padding[??];
                  >> } foo;
                  >>
                  >> I need to fill in the size of padding array here so as to
                  >> make the entire structure size a multiple of 8. Is there
                  >> a way in which I can calculate the padding ? This structure
                  >> will be used on AIX 5.* and RHL.[/color]
                  >
                  > Others have pointed out that there's no completely
                  >guaranteed solution (because the compiler may add more
                  >padding bytes you have no control over). Others have
                  >also offered some non-guaranteed solutions involving
                  >macros and/or two passes. Here's a variation that
                  >might be simpler, if you can tolerate having the padding
                  >appear "after" the struct rather than inside it:
                  >
                  > typedef union { /* not struct */
                  > struct foo_data {
                  > int flag;
                  > char keys[3][9];
                  > } payload;
                  > char overlay[(sizeof(struct foo_data) + 7) / 8];
                  > } foo;
                  >
                  >A disadvantage is that you need to write things like
                  >`fooptr->payload.flag ' instead of `fooptr->flag'.[/color]

                  Another "disadvanta ge" is that you're grossly miscalculating the size of
                  overlay, which is 8 times smaller than it should be! No point in
                  dividing by 8 if you don't multiply back by 8 ;-)

                  Dan
                  --
                  Dan Pop
                  DESY Zeuthen, RZ group
                  Email: Dan.Pop@ifh.de

                  Comment

                  • John Ilves

                    #10
                    Re: Structure padding.

                    This seems to work for me (with gcc on linux):

                    #include <stdio.h>

                    struct foo
                    {
                    int flag : 4; /* force 32 bit */
                    char keys[3][9]; /* 3 * 9 == 27 */
                    int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */
                    };

                    int
                    main()
                    {
                    printf( "struct foo is %d bytes, and %s divisible by 8\n",
                    sizeof(struct foo),
                    sizeof(struct foo) % 8 ? "is not" : "is" );

                    return 0;
                    }

                    Hope it helps,
                    John

                    PS Nice email address. :)


                    Amarendra wrote:[color=blue]
                    > Folks,
                    >
                    > This structure padding issue is bothering me now, could
                    > not locate a satisfactory answer on clc, so here it goes...
                    >
                    > I have a structure, given below:
                    > typedef struct {
                    > int flag;
                    > char keys[3][9];
                    > char padding[??];
                    > } foo;
                    >
                    > I need to fill in the size of padding array here so as to
                    > make the entire structure size a multiple of 8. Is there
                    > a way in which I can calculate the padding ? This structure
                    > will be used on AIX 5.* and RHL.
                    >
                    > Thanks in advance.
                    >
                    > Cheers,
                    > Amar
                    >
                    > --
                    > If you don't want to succeed, nobody will try to stop you.[/color]

                    Comment

                    • Arthur J. O'Dwyer

                      #11
                      Re: Structure padding.


                      On Mon, 21 Jun 2004, John Ilves wrote:[color=blue]
                      >
                      > This seems to work for me (with gcc on linux):[/color]
                      [...][color=blue]
                      > struct foo
                      > {
                      > int flag : 4; /* force 32 bit */[/color]

                      s/32/4/ . (You wrote "4" in the code and "32" in the comment.)
                      [color=blue]
                      > char keys[3][9]; /* 3 * 9 == 27 */
                      > int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */[/color]

                      But where's the missing dollar?

                      Of course, no matter how many bits you use in your struct, GCC will
                      generally pad it out to a decent multiple of 4 or 8 in any event.

                      Because it's annoying as hell.
                      Why not?
                      And don't top-post.

                      -Arthur

                      Comment

                      • Eric Sosman

                        #12
                        Re: Structure padding.

                        John Ilves wrote:[color=blue]
                        > This seems to work for me (with gcc on linux):
                        >
                        > #include <stdio.h>
                        >
                        > struct foo
                        > {
                        > int flag : 4; /* force 32 bit */[/color]

                        ITYM "force 4 bit." Don't feel bad, though: everybody's
                        entitled to one silly mistake per thread (and I've already
                        claimed mine ...)
                        [color=blue]
                        > char keys[3][9]; /* 3 * 9 == 27 */
                        > int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */[/color]

                        `_pad_' happens to be safe in this context, but would
                        be unsafe in most others. Stan Brown's list of identifiers
                        to avoid

                        Portal Live Casino Terbaik di DRAGON222! Nikmati taruhan game spesialis Baccarat dan roulette resmi. Mengajak mencari pengalaman bermain yang lebih seru secara online tanpa harus dateng ke casino offline.


                        is still based on the older C89 Standard and has not been
                        updated for C99, but is still helpful.

                        Oh, and the `: 1' doesn't do what you seem to believe.

                        --
                        Eric.Sosman@sun .com

                        Comment

                        • John Ilves

                          #13
                          Re: Structure padding.



                          Eric Sosman wrote:[color=blue]
                          > John Ilves wrote:
                          >[color=green]
                          >> This seems to work for me (with gcc on linux):
                          >>
                          >> #include <stdio.h>
                          >>
                          >> struct foo
                          >> {
                          >> int flag : 4; /* force 32 bit */[/color]
                          >
                          >
                          > ITYM "force 4 bit." Don't feel bad, though: everybody's
                          > entitled to one silly mistake per thread (and I've already
                          > claimed mine ...)[/color]
                          Heh, oops. Specifying struct field lengths isn't something I've used
                          before, I've just heard about it. Obviously the 4 here should be a 32
                          and the 1 for _pad_ should be an 8 since field lengths are specified in
                          bits not bytes.
                          [color=blue]
                          >[color=green]
                          >> char keys[3][9]; /* 3 * 9 == 27 */
                          >> int _pad_ : 1; /* 4 + 27 + 1 == 32, 32 % 8 == 0 */[/color]
                          >
                          >
                          > `_pad_' happens to be safe in this context, but would
                          > be unsafe in most others. Stan Brown's list of identifiers
                          > to avoid
                          >
                          > http://www.oakroadsystems.com/tech/c-predef.htm
                          >
                          > is still based on the older C89 Standard and has not been
                          > updated for C99, but is still helpful.[/color]
                          I guess that wasn't a very good name. I just wanted to make it clear
                          that that field wasn't intended to be used.
                          [color=blue]
                          >
                          > Oh, and the `: 1' doesn't do what you seem to believe.[/color]
                          Like I said above, it should have been an 8. :-/

                          Comment

                          • Ralmin

                            #14
                            Re: Structure padding.

                            "Arthur J. O'Dwyer" <ajo@nospam.and rew.cmu.edu> wrote:[color=blue]
                            > Hey, good idea! :)
                            >
                            > #include <stdio.h>
                            >
                            > #define PADSIZE(n) (sizeof(struct {int flag; char keys[9][3]; \
                            > char pad[n];}))
                            > #define PADOK(n) (PADSIZE(n)%8== 0)
                            > #define PAD (PADOK(1)? 1: PADOK(2)? 2: PADOK(3)? 3: PADOK(4)? 4: \
                            > PADOK(5)? 5: PADOK(6)? 6: PADOK(7)? 7: PADOK(8)? 8: -1)
                            >
                            > typedef struct {
                            > int flag;
                            > char keys[9][3];
                            > char padding[PAD];
                            > } foo;
                            >
                            > (Naturally, the OP should not use this method. Nor should anyone else.)[/color]

                            LCC-Win32 fails on code like this where a structure type is defined in a
                            situation other than a declaration.

                            Error padsize.c: 12 missing semicolon after structure declaration
                            [Repeated 8 times]

                            This spurious diagnostic actually triggers an "error" condition which
                            prevents creation of an executable.

                            On the other hand, MS VC++'s free command-line compiler also doesn't like
                            your macro much, but at least only warns rather than errors out:

                            padsize.c(12) : warning C4116: unnamed type definition in parentheses

                            GCC, BC++ and Turbo C have no problems with your macro.

                            --
                            Simon.


                            Comment

                            Working...