bitfield & union strange ?!

Discussion in 'C++' started by Claudio, Aug 1, 2004.

  1. Claudio

    Claudio Guest

    hi all

    i put in this email source code so u can copy and paste to verify strange

    first : in this example bit size is a BYTE ?!
    second : in the last printf output is wrong ?

    ?

    best regards all


    #include <stdio.h>


    int main ( void )
    {
    struct snibble
    {
    unsigned a : 1 ;
    unsigned b : 1 ;
    unsigned c : 1 ;
    unsigned d : 1 ;
    } ;

    struct sbyte
    {
    struct snibble high ;
    struct snibble low ;
    } ;
    union ubyte
    {
    struct sbyte a ;
    char c ;
    } ;

    struct snibble n ;
    struct sbyte sb ;
    union ubyte ub ;

    printf ("\n %u " , sizeof ( ub ) ) ;
    printf ("\n %u " , sizeof ( sb ) ) ;
    printf ("\n %u " , sizeof ( n ) ) ;
    printf ("\n %u " , sizeof ( char ) ) ;

    ub.c = 'a' ;

    printf ("\n\n %c " , ub.c ) ;
    printf ("\n %u " , ub.a.high ) ;
    printf ("\n %u " , ub.a.low ) ;



    }
    Claudio, Aug 1, 2004
    #1
    1. Advertising

  2. Claudio

    Jack Klein Guest

    On Sun, 01 Aug 2004 20:14:02 GMT, Claudio <>
    wrote in comp.lang.c++:

    >
    >
    > hi all
    >
    > i put in this email source code so u can copy and paste to verify strange
    >
    > first : in this example bit size is a BYTE ?!
    > second : in the last printf output is wrong ?


    What are you talking about? Do you think that the output of the
    program after you compiled it with your compiler is WRONG? How can we
    tell, you did not show the output on your system when you ran the
    program.

    Here is the output I got when I built and ran the program with one
    particular compiler:

    ========
    8
    8
    4
    1

    a
    97
    0
    ========

    > best regards all
    >
    >
    > #include <stdio.h>
    >
    >
    > int main ( void )
    > {
    > struct snibble
    > {
    > unsigned a : 1 ;
    > unsigned b : 1 ;
    > unsigned c : 1 ;
    > unsigned d : 1 ;
    > } ;


    The size of an 'snibble' struct must be at least one byte, but it may
    be larger. Many implementations allocate bit-field structures in int
    size units, so it may well be sizeof(int).

    > struct sbyte
    > {
    > struct snibble high ;
    > struct snibble low ;
    > } ;


    The size of an 'sbyte' struct must be at least two bytes, but it may
    be larger. It must be at least two times the size of a 'snibble'
    structure.

    > union ubyte
    > {
    > struct sbyte a ;
    > char c ;
    > } ;
    >
    > struct snibble n ;
    > struct sbyte sb ;
    > union ubyte ub ;
    >
    > printf ("\n %u " , sizeof ( ub ) ) ;
    > printf ("\n %u " , sizeof ( sb ) ) ;
    > printf ("\n %u " , sizeof ( n ) ) ;
    > printf ("\n %u " , sizeof ( char ) ) ;
    >
    > ub.c = 'a' ;
    >
    > printf ("\n\n %c " , ub.c ) ;
    > printf ("\n %u " , ub.a.high ) ;
    > printf ("\n %u " , ub.a.low ) ;
    > }


    What is the output of the program when you ran it, and what do you
    think is wrong with it?

    --
    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, Aug 2, 2004
    #2
    1. Advertising

  3. > first : in this example bit size is a BYTE ?!
    no, bit size is always a bit. but you defined:
    struct nibble
    {
    unsigned a:1;
    ...
    };
    in this case _unsigned_ evaluates on most platforms nowadays (since they are
    32-bit architectures) to _unsigned_ _int_ (i.e. to 32 bit, or _four_ byte)!
    you have to declare your struct like this:
    struct nibble
    {
    unsigned char a:1;
    unsigned char b:1;
    unsigned char c:1;
    unsigned char d:1;
    };

    since, the compiler always have to put your struct in at least one byte, you
    also want to declare which bits you want of this byte.
    so the better way is (a..highest bit, d..lowest bit):
    rem.: bits a used from lowest first to highest!

    struct highnibble
    {
    unsigned char unused:4;
    unsigned char d:1;
    unsigned char c:1;
    unsigned char b:1;
    unsigned char a:1;
    };

    struct lownibble
    {
    unsigned char d:1;
    unsigned char c:1;
    unsigned char b:1;
    unsigned char a:1;
    unsigned char unused:4;
    };

    union ubyte
    {
    struct highnibble a;
    struct lownibble b;
    char c;
    }

    than
    printf ("\n %u " , sizeof (struct highnibble) ) ;
    printf ("\n %u " , sizeof (srtuct lownibble) ) ;
    printf ("\n %u " , sizeof ( char ) ) ;
    should all evalute to one!


    in your last use of ubyte
    > union ubyte ub.c = 'a' ;
    >
    > printf ("\n\n %c " , ub.c ) ;
    > printf ("\n %u " , ub.a.high ) ;
    > printf ("\n %u " , ub.a.low ) ;

    you have made the mistake, that the nibble will always access the structure
    - or in your case a 32-bit integer - and not simply four bits. if you want
    to print out a nibble you have to either use a bit-mask, or use c++ and
    operator overload.
    but if you take your structure as used, you will never only access a nibble
    (part) of your byte!

    example (c-code):
    #include <stdio.h>

    #define ACCESS_NIBBLE_LOW(_x) ((_x)&0x0f)
    #define ACCESS_NIBBLE_HIGH(_x) (((_x)&0xf0)>>4)
    int main(void)
    {
    const unsigned char N_HIGH=0xf0, N_LOW=0x0f;
    typedef struct
    {
    unsigned char x:4; /* bits 0..3 */
    unsigned char d:1; /* bit 4 .. 2^4=16 */
    unsigned char c:1; /* bit 5 .. 2^5=32 */
    unsigned char b:1; /* bit 6 .. 2^6=64 */
    unsigned char a:1; /* bit 8 .. 2^7=128*/
    } nibblehigh;

    typedef struct
    {
    unsigned char d:1; /* bit 0 .. 2^0=1 */
    unsigned char c:1; /* bit 1 .. 2^1=2 */
    unsigned char b:1; /* bit 2 .. 2^2=4 */
    unsigned char a:1; /* bit 3 .. 2^3=16*/
    unsigned char y:4; /* bits 4..7 */
    } nibblelow;

    typedef union
    {
    nibblehigh high;
    nibblelow low;
    char c;
    } ubyte;

    printf("\n %u", sizeof(nibblehigh));
    printf("\n %u", sizeof(nibblelow));
    printf("\n %u", sizeof(ubyte));
    printf("\n %u", sizeof(char));

    ubyte ub;
    ub.c = 65+32; /* 'a' */

    printf("\n\n %u %c %c", ub.c, ub.high, ub.low);
    printf("\n %u %u", ACCESS_NIBBLE_HIGH(ub.c), ACCESS_NIBBLE_LOW(ub.c));

    ub.high.c = 0; /* make uppercase (remove bit 5 : 32=2^5) */

    printf("\n\n %u %c %c", ub.c, ub.high, ub.low);
    printf("\n %u %u", ACCESS_NIBBLE_HIGH(ub.c), ACCESS_NIBBLE_LOW(ub.c));

    return 0;
    }

    hope it will help
    godfired
    Gottfried Eibner, Aug 2, 2004
    #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. Matt Garman
    Replies:
    1
    Views:
    663
    Matt Garman
    Apr 25, 2004
  2. zb32

    bitfield optimizations

    zb32, Jul 13, 2004, in forum: C++
    Replies:
    1
    Views:
    1,063
    David Harmon
    Jul 13, 2004
  3. Replies:
    0
    Views:
    521
  4. Davide Bruzzone
    Replies:
    9
    Views:
    378
    Adam S. Roan
    Aug 27, 2003
  5. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    867
    Chris Torek
    Apr 26, 2004
Loading...

Share This Page