bitfield in struct and padding

Discussion in 'C Programming' started by Stanley Rice, Nov 10, 2011.

  1. Stanley Rice

    Stanley Rice Guest

    Dear all

    Here I declare a structure as follows:

    struct flag
    {
    unsigned int a : 8; /* 1 - 7 is yield the same result*/
    char b;
    char c;
    char d;
    };

    and sizeof(struct flag) equals 4, which is intuitive.

    But when I make a little modification, where the bitwidth allocated to
    a is 9:

    struct flag
    {
    unsigned int a : 9; /* modification here */
    char b;
    char c;
    char d;
    };

    and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
    are allocated to variable a, and 3 bytes are allocated to the
    following char type variable.

    I want to know how many bytes are allocated to variable a? and how the
    padding in the obove structure performs.
    Stanley Rice, Nov 10, 2011
    #1
    1. Advertising

  2. Stanley Rice

    tom st denis Guest

    On Nov 10, 9:29 am, Stanley Rice <> wrote:
    > Dear all
    >
    > Here I declare a structure as follows:
    >
    > struct flag
    > {
    >     unsigned int    a : 8; /* 1 - 7 is yield the same result*/
    >     char            b;
    >     char            c;
    >     char            d;
    >
    > };
    >
    > and sizeof(struct flag) equals 4, which is intuitive.
    >
    > But when I make a little modification, where the bitwidth allocated to
    > a is 9:
    >
    > struct flag
    > {
    >     unsigned int    a : 9; /* modification here */
    >     char            b;
    >     char            c;
    >     char            d;
    >
    > };
    >
    > and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
    > are allocated to variable a, and 3 bytes are allocated to the
    > following char type variable.
    >
    > I want to know how many bytes are allocated to variable a? and how the
    > padding in the obove structure performs.


    That's more of a compiler question than anything. Chances are good
    you're on a 32 or 64-bit host where it is optimizing the structure by
    padding it out to 32-bits, then adding padding to the structure as a
    whole.

    There are usually [per-compiler] pragmas to be had to pack structure
    densely. They're not portable.

    From experience, if you are using bit-fields it's probably because

    a) You're writing non-portable code that talks to hardware

    or

    b) You're trying to avoid having to use & operators explicitly in your
    code when dealing with truncated values...

    Personally I've never used bitfields in anything I've written in the
    19 years I've been using C [both as an amateur and a pro]...

    Tom
    tom st denis, Nov 10, 2011
    #2
    1. Advertising

  3. Stanley Rice <> writes:

    > Here I declare a structure as follows:
    >
    > struct flag
    > {
    > unsigned int a : 8; /* 1 - 7 is yield the same result*/
    > char b;
    > char c;
    > char d;
    > };
    >
    > and sizeof(struct flag) equals 4, which is intuitive.
    >
    > But when I make a little modification, where the bitwidth allocated to
    > a is 9:
    >
    > struct flag
    > {
    > unsigned int a : 9; /* modification here */
    > char b;
    > char c;
    > char d;
    > };
    >
    > and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
    > are allocated to variable a, and 3 bytes are allocated to the
    > following char type variable.
    >
    > I want to know how many bytes are allocated to variable a? and how the
    > padding in the obove structure performs.


    I don't think there is a simple way to find out. It must be more than 1
    on machine with CHAR_BIT==8, but other than that all you can tell is
    where 'b' is. If, say, offsetof(struct flag, b) == 4, you can't tell if
    this is due to padding or the size of the unit used to hold 'a', but
    does it matter?

    More to the point, what is the reason you need to know? What are you
    trying to achieve? If your objective is to control the layout, your
    compiler may provide non-standard ways to do that. But even so, I'd
    want to know the ultimate objective, because there may be better ways to
    achieve it.

    --
    Ben.
    Ben Bacarisse, Nov 10, 2011
    #3
  4. On Nov 10, 4:29 pm, Stanley Rice <> wrote:
    > Dear all
    >
    > Here I declare a structure as follows:
    >
    > struct flag
    > {
    >     unsigned int    a : 8; /* 1 - 7 is yield the same result*/
    >     char            b;
    >     char            c;
    >     char            d;
    >
    > };
    >
    > and sizeof(struct flag) equals 4, which is intuitive.
    >
    > But when I make a little modification, where the bitwidth allocated to
    > a is 9:
    >
    > struct flag
    > {
    >     unsigned int    a : 9; /* modification here */
    >     char            b;
    >     char            c;
    >     char            d;
    >
    > };
    >
    > and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
    > are allocated to variable a, and 3 bytes are allocated to the
    > following char type variable.
    >
    > I want to know how many bytes are allocated to variable a? and how the
    > padding in the obove structure performs.
    >

    You can easily find out.

    struct flag s;
    printf("%d %d %d %d\n", (int) (&s.b - &s), (int)(&s.c - &s), (int)
    (&s.d - &s), (int) sizeof(s));

    That will tell you where the padding has been inserted. Clearly on any
    system with 8 bit bytes you will need some padding, since 9 bits can't
    fit into a whole number of bytes.
    Malcolm McLean, Nov 10, 2011
    #4
  5. On Nov 10, 9:40 pm, tom st denis <> wrote:
    > From experience, if you are using bit-fields it's probably because
    >
    > a) You're writing non-portable code that talks to hardware, or


    > b) You're trying to avoid having to use & operators explicitly in your
    > code when dealing with truncated values..., [or]


    and I would add
    c) taking advantage, in routine(s) you want optimized for
    speed, of some compilers which deliver better opcodes when
    bitfield is used (True of the Sun 68k 1988 compiler;
    Perhaps present-day compilers are so good,
    this is no longer a problem), or

    d) for better readability, e.g. to write
    q->bptr = dval; /* Stmt D1 */
    instead of
    q->d[FADDR] = q->d[FADDR] & ~MASKFOO \
    | dval << FOOSHIF; /* Stmt D2 */

    > Personally I've never used bitfields in anything I've written in the
    > 19 years I've been using C [both as an amateur and a pro]...
    >
    > Tom


    I can say the same, more-or-less. It is the concern about
    portability ease that often leads the coder to avoid them unless
    there is a very important benefit.

    Looking at my example (d) above, I consider that the first form
    has a significant readability win. What do others think?

    James Dow Allen
    James Dow Allen, Nov 10, 2011
    #5
  6. Stanley Rice

    tom st denis Guest

    On Nov 10, 1:53 pm, James Dow Allen <> wrote:
    > On Nov 10, 9:40 pm, tom st denis <> wrote:
    >
    > > From experience, if you are using bit-fields it's probably because

    >
    > > a) You're writing non-portable code that talks to hardware, or
    > > b) You're trying to avoid having to use & operators explicitly in your
    > > code when dealing with truncated values..., [or]

    >
    > and I would add
    > c) taking advantage, in routine(s) you want optimized for
    > speed, of some compilers which deliver better opcodes when
    > bitfield is used (True of the Sun 68k 1988 compiler;
    > Perhaps present-day compilers are so good,
    > this is no longer a problem), or
    >
    > d) for better readability, e.g. to write
    >     q->bptr = dval;  /* Stmt D1 */
    > instead of
    >     q->d[FADDR] = q->d[FADDR] & ~MASKFOO \
    >             | dval << FOOSHIF; /* Stmt D2 */
    >
    > > Personally I've never used bitfields in anything I've written in the
    > > 19 years I've been using C [both as an amateur and a pro]...

    >
    > > Tom

    >
    > I can say the same, more-or-less.  It is the concern about
    > portability ease that often leads the coder to avoid them unless
    > there is a very important benefit.
    >
    > Looking at my example (d) above, I consider that the first form
    > has a significant readability win.  What do others think?


    I'd use a macro....

    q->d = SET_D_FIELD(potato);

    or something to that effect (I write HW drivers a large part of my day
    lately...).

    Tom
    tom st denis, Nov 10, 2011
    #6
  7. Malcolm McLean <> writes:
    > On Nov 10, 4:29 pm, Stanley Rice <> wrote:
    >> Here I declare a structure as follows:
    >>
    >> struct flag
    >> {
    >>     unsigned int    a : 8; /* 1 - 7 is yield the same result*/
    >>     char            b;
    >>     char            c;
    >>     char            d;
    >>
    >> };
    >>
    >> and sizeof(struct flag) equals 4, which is intuitive.
    >>
    >> But when I make a little modification, where the bitwidth allocated to
    >> a is 9:
    >>
    >> struct flag
    >> {
    >>     unsigned int    a : 9; /* modification here */
    >>     char            b;
    >>     char            c;
    >>     char            d;
    >>
    >> };
    >>
    >> and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
    >> are allocated to variable a, and 3 bytes are allocated to the
    >> following char type variable.
    >>
    >> I want to know how many bytes are allocated to variable a? and how the
    >> padding in the obove structure performs.
    >>

    > You can easily find out.
    >
    > struct flag s;
    > printf("%d %d %d %d\n", (int) (&s.b - &s), (int)(&s.c - &s), (int)
    > (&s.d - &s), (int) sizeof(s));


    I don't believe that will compile. &s.b is of type char*; &s is of type
    struct flag*.

    Just use the offsetof() macro, defined in <stddef.h>.

    Here's a program I just threw together (note that offsetof() can't be
    applied to a bit-field).

    #include <stdio.h>
    #include <stddef.h>

    struct flag7
    {
    unsigned int a : 7;
    char b;
    char c;
    char d;
    };

    struct flag8
    {
    unsigned int a : 8;
    char b;
    char c;
    char d;
    };


    struct flag9
    {
    unsigned int a : 9;
    char b;
    char c;
    char d;
    };

    int main(void) {
    printf("sizeof (struct flag7) = %d\n", (int)sizeof (struct flag7));
    printf(" b at %d\n", (int)offsetof(struct flag7, b));
    printf(" c at %d\n", (int)offsetof(struct flag7, c));
    printf(" c at %d\n", (int)offsetof(struct flag7, d));

    printf("sizeof (struct flag8) = %d\n", (int)sizeof (struct flag8));
    printf(" b at %d\n", (int)offsetof(struct flag8, b));
    printf(" c at %d\n", (int)offsetof(struct flag8, c));
    printf(" c at %d\n", (int)offsetof(struct flag8, d));

    printf("sizeof (struct flag9) = %d\n", (int)sizeof (struct flag9));
    printf(" b at %d\n", (int)offsetof(struct flag9, b));
    printf(" c at %d\n", (int)offsetof(struct flag9, c));
    printf(" c at %d\n", (int)offsetof(struct flag9, d));

    return 0;
    }

    On my system, the output is:

    sizeof (struct flag7) = 4
    b at 1
    c at 2
    c at 3
    sizeof (struct flag8) = 4
    b at 1
    c at 2
    c at 3
    sizeof (struct flag9) = 8
    b at 2
    c at 3
    c at 4

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 10, 2011
    #7
    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. Erik Cato

    bitfield and enum, is this legal?

    Erik Cato, Feb 23, 2004, in forum: C Programming
    Replies:
    8
    Views:
    6,276
    Barry Schwarz
    Feb 27, 2004
  2. Chris Fogelklou
    Replies:
    36
    Views:
    1,376
    Chris Fogelklou
    Apr 20, 2004
  3. Hallvard B Furuseth

    Padding bits and struct assignment

    Hallvard B Furuseth, Dec 27, 2006, in forum: C Programming
    Replies:
    5
    Views:
    648
    Eric Sosman
    Dec 27, 2006
  4. mc
    Replies:
    5
    Views:
    2,508
  5. Replies:
    13
    Views:
    352
    glen herrmannsfeldt
    May 5, 2013
Loading...

Share This Page