Alternative approach to bitfields

Discussion in 'C Programming' started by W Karas, Jul 23, 2012.

  1. W Karas

    W Karas Guest

    The idea is to define the bitfields using a "map" structure of arrays of char, with each char corresponding to a bit in an unsigned integer. Here is some example code:

    /* Notes
    ** 1. parameters to these macros may appear multiple times in the
    ** macro definition, so do not use expresions with side-effects as
    ** actual parameters.
    ** 2. If parameters to these macros are not in the correct range,
    ** results are undetermined.
    */

    /* Get the value of the bitfield with the given WIDTH at the offset OFS in
    ** the rvalue RV of unsigned integer type UT.
    */
    #define BF_GET_N(UT, RV, WIDTH, OFS) \
    (((RV) >> (OFS)) & BF_H_MW(UT, WIDTH))

    /* Logically OR the value VAL into lvalue LV after left-bit-shifting it
    ** by OFS bits.
    */
    #define BF_OR_N(LV, OFS, VAL) \
    { BF_H_OR_N_EXPR(LV, OFS, VAL); }

    /* Set the value VAL in the bitfield with the given WIDTH at the offset OFS
    ** in the lvalue LV of unsigned integer type UT.
    */
    #define BF_SET_N(UT, LV, WIDTH, OFS, VAL) \
    { ((WIDTH) >= (sizeof(UT) * CHAR_BIT)) ? \
    (*&(LV) = (VAL)) : \
    (*&(LV) &= ~(BF_H_MW(UT, WIDTH) << (OFS)), \
    BF_H_OR_N_EXPR(LV, OFS, VAL)); }

    /* A "bitfield map structure" is recursively defined as a C/POD struct or
    ** union where each member is an array of char or a bitfield map structure.
    ** Each array of char represents a bitfield. The sizeof the array gives
    ** the width of the bitfield. The byte offset of the array from the
    ** start of the top-level structure gives the offset of the bitfield.
    */

    /* Get the value of the bitfield in the rvalue RV of unsigned integer type
    ** UT corresponding to the field FLD in bitfield map structure MSTRU.
    */
    #define BF_GET(UT, RV, MSTRU, FLD) \
    BF_GET_N(UT, RV, BF_H_WIDTH(MSTRU, FLD), BF_H_OFS(MSTRU, FLD))

    /* Logically OR the value VAL into value of the bitfield in the rvalue RV of
    ** unsigned integer type ** UT corresponding to the field FLD in bitfield map
    ** structure MSTRU.
    */
    #define BF_OR(LV, MSTRU, FLD, VAL) \
    BF_OR_N(LV, BF_H_OFS(MSTRU, FLD), VAL)

    /* Set the value VAL in the bitfield in the rvalue RV of unsigned integer
    ** type UT corresponding to the field FLD in bitfield map structure MSTRU.
    */
    #define BF_SET(UT, LV, MSTRU, FLD, VAL) \
    BF_SET_N(UT, LV, BF_H_WIDTH(MSTRU, FLD), BF_H_OFS(MSTRU, FLD), VAL)

    /* --------------------------------------------------------------------- */

    /* "Private" macros, not meant for direct use. */

    #include <limits.h>

    /* Mask of WIDTH and type UT.
    */
    #define BF_H_MW(UT, WIDTH) \
    ((UT) (((WIDTH) >= (sizeof(UT) * CHAR_BIT)) ? \
    (~ (UT) 0) : ((((UT) 1) << (WIDTH)) - 1)))

    /* BF_OR_N as expression not statement.
    */
    #define BF_H_OR_N_EXPR(LV, OFS, VAL) \
    (*&(LV) |= ((VAL) << (OFS)))

    /* Returns offset of bitfield corresponding to char array FLD in bitfield
    ** map structure MSTRU.
    */
    #define BF_H_WIDTH(MSTRU, FLD) \
    (sizeof(((MSTRU *) 0x100)->FLD))

    /* Returns width of bitfield corresponding to char array FLD in bitfield
    ** map structure MSTRU.
    */
    #define BF_H_OFS(MSTRU, FLD) \
    ((((MSTRU *) 0x100)->FLD) - ((char *) 0x100))

    /* These macros lay out the bit fields with higher offsets at higher
    ** significance, but the reverse is also possible.
    */

    /* --------------------------------------------------------------------- */

    /* Test code */

    typedef struct
    {
    union
    {
    /* Array of 4 5-bit-wide bitfields (cool eh?). */
    char fa[4][5];

    struct
    {
    char f1[6], f2[14];
    }
    sm;
    }
    u;

    char f3[12];
    }
    Map_bf;

    #include <stdio.h>
    #include <stdlib.h>

    void bail(void)
    {
    printf("FAIL\n");
    exit(1);
    }

    int main(void)
    {
    unsigned va[4], v1, v2, v3, i, v;

    v = 0xabcd1234;

    for (i = 0; i < 4; ++i)
    va = BF_GET(unsigned, v, Map_bf, u.fa);
    v3 = BF_GET(unsigned, v, Map_bf, f3);

    if (v != 0xabcd1234)
    bail();

    v = 0x1234abcd;

    for (i = 0; i < 4; ++i)
    BF_SET(unsigned, v, Map_bf, u.fa, va)
    BF_SET(unsigned, v, Map_bf, f3, v3);

    if (v != 0xabcd1234)
    bail();

    v = 0xabcd1234;

    v1 = BF_GET(unsigned, v, Map_bf, u.sm.f1);
    v2 = BF_GET(unsigned, v, Map_bf, u.sm.f2);
    v3 = BF_GET(unsigned, v, Map_bf, f3);

    if (v != 0xabcd1234)
    bail();

    v = 0x1234abcd;

    BF_SET(unsigned, v, Map_bf, u.sm.f1, v1)
    BF_SET(unsigned, v, Map_bf, u.sm.f2, v2)
    BF_SET(unsigned, v, Map_bf, f3, v3)

    if (v != 0xabcd1234)
    bail();

    v = 0xabcd1234;

    for (i = 0; i < 4; ++i)
    va = BF_GET(unsigned, v, Map_bf, u.fa);
    v3 = BF_GET(unsigned, v, Map_bf, f3);

    v = 0;

    for (i = 0; i < 4; ++i)
    BF_OR(v, Map_bf, u.fa, va)
    BF_OR(v, Map_bf, f3, v3)

    if (v != 0xabcd1234)
    bail();

    v = 0xabcd1234;

    v1 = BF_GET(unsigned, v, Map_bf, u.sm.f1);
    v2 = BF_GET(unsigned, v, Map_bf, u.sm.f2);
    v3 = BF_GET(unsigned, v, Map_bf, f3);

    v = 0;

    BF_OR(v, Map_bf, u.sm.f1, v1)
    BF_OR(v, Map_bf, u.sm.f2, v2)
    BF_OR(v, Map_bf, f3, v3)

    if (v != 0xabcd1234)
    bail();

    printf("SUCCESS\n");

    return(0);
    }
    W Karas, Jul 23, 2012
    #1
    1. Advertising

  2. W Karas

    Ike Naar Guest

    On 2012-07-23, W Karas <> wrote:
    > /* Returns offset of bitfield corresponding to char array FLD in bitfield
    > ** map structure MSTRU.
    > */
    > #define BF_H_WIDTH(MSTRU, FLD) \
    > (sizeof(((MSTRU *) 0x100)->FLD))
    >
    > /* Returns width of bitfield corresponding to char array FLD in bitfield
    > ** map structure MSTRU.
    > */
    > #define BF_H_OFS(MSTRU, FLD) \
    > ((((MSTRU *) 0x100)->FLD) - ((char *) 0x100))


    Were the comments for these macros swapped?
    Ike Naar, Jul 23, 2012
    #2
    1. Advertising

  3. W Karas

    Guest

    On Monday, July 23, 2012 2:15:13 AM UTC-4, Ike Naar wrote:
    > On 2012-07-23, W Karas wrote:
    > &gt; /* Returns offset of bitfield corresponding to char array FLD in bitfield
    > &gt; ** map structure MSTRU.
    > &gt; */
    > &gt; #define BF_H_WIDTH(MSTRU, FLD) \
    > &gt; (sizeof(((MSTRU *) 0x100)-&gt;FLD))
    > &gt;
    > &gt; /* Returns width of bitfield corresponding to char array FLD in bitfield
    > &gt; ** map structure MSTRU.
    > &gt; */
    > &gt; #define BF_H_OFS(MSTRU, FLD) \
    > &gt; ((((MSTRU *) 0x100)-&gt;FLD) - ((char *) 0x100))
    >
    > Were the comments for these macros swapped?


    oops
    , Jul 23, 2012
    #3
  4. W Karas

    Jorgen Grahn Guest

    On Mon, 2012-07-23, W Karas wrote:
    > The idea is to define the bitfields using a "map" structure of

    ....

    Please don't multipost. This (or a very similar) posting also showed
    up in comp.lang.c++. Crosspost if you feel you must.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Jul 24, 2012
    #4
    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:
    404
    Dan Pop
    Feb 17, 2004
  3. rohit
    Replies:
    23
    Views:
    1,733
    Dave Thompson
    Jun 10, 2004
  4. Grumfish
    Replies:
    2
    Views:
    366
    Bengt Richter
    Aug 19, 2003
  5. W Karas
    Replies:
    9
    Views:
    458
    W Karas
    Jul 24, 2012
Loading...

Share This Page