Bitfields in struct

Discussion in 'C Programming' started by Jason Curl, Oct 11, 2005.

  1. Jason Curl

    Jason Curl Guest

    Hello C Group,

    From what I remember, it is implementation dependent the way that a
    compiler may order bitfields in a struct. In the example program I give,
    Solaris Sparc gives one result, Intel x86 gives another result (for the
    GCC compiler).

    Is there a portable way to test how this information is stored? In
    particular, will the result of the program below always result in c
    being 0x01 or 0x80? Does the compiler allow for padding so that the
    result may also be 0x00?

    For example:

    #include <stdio.h>

    struct bitfield {
    int b7:1;
    int b6:1;
    int b5:1;
    int b4:1;
    int b3:1;
    int b2:1;
    int b1:1;
    int b0:1;
    };

    union highlow {
    struct bitfield bf;
    unsigned char c;
    };

    int main(void)
    {
    union highlow h;

    h.c = 0;
    h.bf.b0 = 1;

    if (h.c == 0x80) {
    printf("LSB machine\n");
    } else {
    printf("MSB machine\n");
    }
    printf("c = %02x\n", h.c);
    }

    --
    Jason.
    Jason Curl, Oct 11, 2005
    #1
    1. Advertising

  2. Jason Curl

    Jack Klein Guest

    On Tue, 11 Oct 2005 13:21:00 +0200, Jason Curl
    <> wrote in comp.lang.c:

    > Hello C Group,
    >
    > From what I remember, it is implementation dependent the way that a
    > compiler may order bitfields in a struct. In the example program I give,
    > Solaris Sparc gives one result, Intel x86 gives another result (for the
    > GCC compiler).
    >
    > Is there a portable way to test how this information is stored? In
    > particular, will the result of the program below always result in c
    > being 0x01 or 0x80? Does the compiler allow for padding so that the
    > result may also be 0x00?


    The result might be 0x01. It might even be 0x80, but that is rather
    unlikely.

    > For example:
    >
    > #include <stdio.h>
    >
    > struct bitfield {
    > int b7:1;


    Note that when used to define bit-field members, plain 'int' is not
    necessarily signed int. It may be unsigned int, that is
    implementation defined.

    Also note that a one-bit signed bit-field is dicey. It can have two
    values, but are they 0 and 1 or 0 and -1? Frankly the C standard
    leaves this ambiguous, and the behavior of compilers varies.

    For single bit bit-fields, it is safest to explicitly used unsigned
    int, or, if you have a C99 conforming compiler, _Bool which is an
    unsigned integer type.

    > int b6:1;
    > int b5:1;
    > int b4:1;
    > int b3:1;
    > int b2:1;
    > int b1:1;
    > int b0:1;
    > };


    You seem to assume that this bit-field will occupy exactly 8 bits. No
    such requirement or guarantee exists in the C standard. There are
    some platforms that will use a whole int or larger type, 16 or 32 or
    more bits, not just 8.

    > union highlow {
    > struct bitfield bf;
    > unsigned char c;
    > };
    >
    > int main(void)
    > {
    > union highlow h;
    >
    > h.c = 0;
    > h.bf.b0 = 1;
    >
    > if (h.c == 0x80) {
    > printf("LSB machine\n");
    > } else {
    > printf("MSB machine\n");
    > }
    > printf("c = %02x\n", h.c);
    > }


    Do you actually mean "LSb" and "MSb", that is least and most
    significant bit?

    Padding has nothing to do with it. Assume an implementation that will
    use an int to store the bit-field struct, which is not at all unusual.
    So the underlying int has, for example, 32 bits. It is
    implementation-defined whether bit-fields are allocated starting with
    the most significant or least significant bit, but assume a
    little-endian architecture with CHAR_BIT 8 that starts allocating from
    the most significant bit.

    In that case, the representation of the bit-field interpreted as an
    unsigned 32 bit int would be 0x80000000, and it would appear in
    memory, from lowest to highest address as 0x00, 0x00, 0x00, 0x80.

    Now suppose a bit-endian implementation that starts allocating
    bit-fields from the least significant bit. In that case, the
    representation of the unsigned bit-field interpreted as a 32-bit
    unsigned int would be 0x00000001, and it would appear in memory as
    0x00, 0x00, 0x00, 0x01.

    You are assuming that because you define a bit-field struct containing
    8 bits, and you overlay an unsigned char over its first byte (and you
    assume that your char has exactly 8 bits), that all of the 8 bits in
    the bit-field will lie within that 8-bit char. There is no guarantee
    of that at all.

    --
    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++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Oct 12, 2005
    #2
    1. Advertising

  3. Jason Curl

    Jason Curl Guest

    Jack Klein wrote:
    > On Tue, 11 Oct 2005 13:21:00 +0200, Jason Curl
    > <> wrote in comp.lang.c:
    >
    >> Is there a portable way to test how this information is stored? In
    >> particular, will the result of the program below always result in c
    >> being 0x01 or 0x80? Does the compiler allow for padding so that the
    >> result may also be 0x00?

    >
    > The result might be 0x01. It might even be 0x80, but that is rather
    > unlikely.
    >
    >> For example:
    >>
    >> #include <stdio.h>
    >>
    >> struct bitfield {
    >> int b7:1;

    >
    > Note that when used to define bit-field members, plain 'int' is not
    > necessarily signed int. It may be unsigned int, that is
    > implementation defined.
    >
    > Also note that a one-bit signed bit-field is dicey. It can have two
    > values, but are they 0 and 1 or 0 and -1? Frankly the C standard
    > leaves this ambiguous, and the behavior of compilers varies.
    >
    >> int b6:1;
    >> int b5:1;
    >> int b4:1;
    >> int b3:1;
    >> int b2:1;
    >> int b1:1;
    >> int b0:1;
    >> };

    >
    > You seem to assume that this bit-field will occupy exactly 8 bits. No
    > such requirement or guarantee exists in the C standard. There are
    > some platforms that will use a whole int or larger type, 16 or 32 or
    > more bits, not just 8.
    >
    >> union highlow {
    >> struct bitfield bf;
    >> unsigned char c;
    >> };
    >>
    >> int main(void)
    >> {
    >> union highlow h;
    >>
    >> h.c = 0;
    >> h.bf.b0 = 1;
    >>
    >> if (h.c == 0x80) {
    >> printf("LSB machine\n");
    >> } else {
    >> printf("MSB machine\n");
    >> }
    >> printf("c = %02x\n", h.c);
    >> }

    >
    > Do you actually mean "LSb" and "MSb", that is least and most
    > significant bit?


    Yes, LSb and MSb.

    > Padding has nothing to do with it. Assume an implementation that will
    > use an int to store the bit-field struct, which is not at all unusual.
    > So the underlying int has, for example, 32 bits. It is
    > implementation-defined whether bit-fields are allocated starting with
    > the most significant or least significant bit, but assume a
    > little-endian architecture with CHAR_BIT 8 that starts allocating from
    > the most significant bit.
    >
    > In that case, the representation of the bit-field interpreted as an
    > unsigned 32 bit int would be 0x80000000, and it would appear in
    > memory, from lowest to highest address as 0x00, 0x00, 0x00, 0x80.
    >
    > Now suppose a bit-endian implementation that starts allocating
    > bit-fields from the least significant bit. In that case, the
    > representation of the unsigned bit-field interpreted as a 32-bit
    > unsigned int would be 0x00000001, and it would appear in memory as
    > 0x00, 0x00, 0x00, 0x01.


    I'm assuming CHAR_BIT is 8, as required for POSIX. Must a conforming C
    compiler must be consistent in how it allocates the bits?

    For example, either 0x00000001, 0x80000000, 0x00008000 or 0x00000080 for
    a 32-bit implementation. A 64-bit implementation would then possibly be
    similar.

    Or is this also in no way guaranteed by the C-standard? <ot> how about
    these questions applied the posix standard? </ot>

    >
    > You are assuming that because you define a bit-field struct containing
    > 8 bits, and you overlay an unsigned char over its first byte (and you
    > assume that your char has exactly 8 bits), that all of the 8 bits in
    > the bit-field will lie within that 8-bit char. There is no guarantee
    > of that at all.
    >


    Rephrasing my question, does the C-standard specify (so that there are a
    small number of limited possibilities) how two elements in a union overlay?

    Thanks,
    Jason.
    Jason Curl, Oct 12, 2005
    #3
    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. Juha Kettunen
    Replies:
    9
    Views:
    363
    Leor Zolman
    Apr 10, 2004
  2. Régis Troadec

    About bitfields

    Régis Troadec, Feb 14, 2004, in forum: C Programming
    Replies:
    8
    Views:
    402
    Dan Pop
    Feb 17, 2004
  3. Chris Fogelklou
    Replies:
    36
    Views:
    1,371
    Chris Fogelklou
    Apr 20, 2004
  4. sarathy

    Questions on bitfields and struct

    sarathy, Jul 20, 2006, in forum: C Programming
    Replies:
    7
    Views:
    423
    Andrew Poelstra
    Jul 22, 2006
  5. Karthik
    Replies:
    2
    Views:
    862
    Lawrence D'Oliveiro
    Jun 19, 2009
Loading...

Share This Page