bitfields in union : defined behaviour ?

Discussion in 'C Programming' started by gert.vierman@gmail.com, Jan 5, 2006.

  1. Guest

    Hello,

    Here is some code mixing bitfields and longs in an union.
    Any comments on the validity and portability of this program ?
    Thank you very much.

    #include <stdio.h>

    union msg_t {

    struct elem {
    unsigned long foo: 16;
    unsigned long bar: 12;
    unsigned long type: 4;
    unsigned long length: 32;
    } elem;

    unsigned long data[2];

    } ;

    int main(int argc, char **argv)
    {
    union msg_t msgh;

    msgh.elem.bar = 0x2;
    msgh.elem.foo = 0x3;
    msgh.elem.length = 0x100;

    printf("%08x\n", msgh.data[0]);
    printf("%08x\n", msgh.data[1]);

    return 0;
    }
    , Jan 5, 2006
    #1
    1. Advertising

  2. Guest

    wrote:
    > Hello,
    >
    > Here is some code mixing bitfields and longs in an union.
    > Any comments on the validity and portability of this program ?
    > Thank you very much.
    >
    > #include <stdio.h>
    >
    > union msg_t {
    >
    > struct elem {
    > unsigned long foo: 16;
    > unsigned long bar: 12;
    > unsigned long type: 4;
    > unsigned long length: 32;
    > } elem;
    >
    > unsigned long data[2];
    >
    > } ;
    >
    > int main(int argc, char **argv)
    > {
    > union msg_t msgh;
    >
    > msgh.elem.bar = 0x2;
    > msgh.elem.foo = 0x3;
    > msgh.elem.length = 0x100;
    >
    > printf("%08x\n", msgh.data[0]);
    > printf("%08x\n", msgh.data[1]);
    >
    > return 0;
    > }


    I am sorry, all 'unsigned longs' should be replaced by the proper type
    which is guaranteed to be an unsigned 32 bits int on all platforms.
    maybe uint32_t from stdint.h ?
    , Jan 5, 2006
    #2
    1. Advertising

  3. Richard Bos Guest

    wrote:

    > Here is some code mixing bitfields and longs in an union.
    > Any comments on the validity and portability of this program ?


    > union msg_t {
    > struct elem {
    > unsigned long foo: 16;
    > unsigned long bar: 12;
    > unsigned long type: 4;
    > unsigned long length: 32;
    > } elem;
    > unsigned long data[2];
    > } ;


    > union msg_t msgh;
    >
    > msgh.elem.bar = 0x2;
    > msgh.elem.foo = 0x3;
    > msgh.elem.length = 0x100;
    >
    > printf("%08x\n", msgh.data[0]);
    > printf("%08x\n", msgh.data[1]);


    Yes. This is not portable ISO C. Assigning a value to any member of a
    union makes all other members take unspecified (maybe even undefined; I
    can't remember) values. One reason for this is that you don't know how
    your bit fields are arranged inside their parent members.

    Richard
    Richard Bos, Jan 5, 2006
    #3
  4. Guest

    Richard Bos wrote:
    > wrote:
    >
    > > Here is some code mixing bitfields and longs in an union.
    > > Any comments on the validity and portability of this program ?

    >
    > > union msg_t {
    > > struct elem {
    > > unsigned long foo: 16;
    > > unsigned long bar: 12;
    > > unsigned long type: 4;
    > > unsigned long length: 32;
    > > } elem;
    > > unsigned long data[2];
    > > } ;

    >
    > > union msg_t msgh;
    > >
    > > msgh.elem.bar = 0x2;
    > > msgh.elem.foo = 0x3;
    > > msgh.elem.length = 0x100;
    > >
    > > printf("%08x\n", msgh.data[0]);
    > > printf("%08x\n", msgh.data[1]);

    >
    > Yes. This is not portable ISO C. Assigning a value to any member of a
    > union makes all other members take unspecified (maybe even undefined; I
    > can't remember) values. One reason for this is that you don't know how
    > your bit fields are arranged inside their parent members.


    Thank you, that is what I already expected.
    , Jan 5, 2006
    #4
  5. writes:
    > Here is some code mixing bitfields and longs in an union.
    > Any comments on the validity and portability of this program ?
    > Thank you very much.
    >
    > #include <stdio.h>
    >
    > union msg_t {
    >
    > struct elem {
    > unsigned long foo: 16;
    > unsigned long bar: 12;
    > unsigned long type: 4;
    > unsigned long length: 32;
    > } elem;
    >
    > unsigned long data[2];
    >
    > } ;
    >
    > int main(int argc, char **argv)
    > {
    > union msg_t msgh;
    >
    > msgh.elem.bar = 0x2;
    > msgh.elem.foo = 0x3;
    > msgh.elem.length = 0x100;
    >
    > printf("%08x\n", msgh.data[0]);
    > printf("%08x\n", msgh.data[1]);
    >
    > return 0;
    > }


    Apart from the problems of accessing one member of a union after
    storing a value in another member, the only portable types for
    bitfields are int, unsigned int, signed int, and (in C99) _Bool.
    Implementations may support other types as an extension.

    Any bit fields larger than 16 bits are non-portable (since int is only
    required to be 16 or more bits).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 5, 2006
    #5
  6. dwks Guest

    And you shouldn't make a bit field 8 bits or 16 or something -- in
    those cases you can just use a char or something.
    dwks, Jan 8, 2006
    #6
  7. "dwks" <> wrote in message
    news:...
    > And you shouldn't make a bit field 8 bits or 16 or something -- in
    > those cases you can just use a char or something.


    I've used :8 to guarantee eight bits.

    This was back in pre-ANSI days, with a program running on two platforms, one of
    which had nine bit characters. I think I did it to save a lot of masking
    operations, which were making the code hard to read. And which someone would
    always forget at least one of when adding a new feature.

    - Bill
    William J. Leary Jr., Jan 9, 2006
    #7
  8. "dwks" <> writes:
    > And you shouldn't make a bit field 8 bits or 16 or something -- in
    > those cases you can just use a char or something.


    Please read <http://cfaj.freeshell.org/google/> and follow its advice.

    There's no guarantee that a char is 8 bits. There's no guarantee that
    8-bit and 16-bit types even exists (I've used a system with no
    predefined 16-bit integer type). The only guarantees are:

    char >=8
    short >=16
    int >=16
    long >=32
    long long >=64 (C99 only)
    char <= short <= int <= long <= long long

    (I'm using a shorthand notation that should be clear enough, but
    doesn't correspond to anything you'd see in a C expression.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 9, 2006
    #8
    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. Matt Garman
    Replies:
    1
    Views:
    654
    Matt Garman
    Apr 25, 2004
  2. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    854
    Chris Torek
    Apr 26, 2004
  3. Oodini
    Replies:
    1
    Views:
    1,754
    Keith Thompson
    Sep 27, 2005
  4. Ed
    Replies:
    5
    Views:
    326
    James Kanze
    Aug 13, 2008
  5. Noob

    Portability issues (union, bitfields)

    Noob, Nov 4, 2009, in forum: C Programming
    Replies:
    7
    Views:
    1,038
    John Temples
    Nov 6, 2009
Loading...

Share This Page