Velocity Reviews > Alternative approach to bitfields

# Alternative approach to bitfields

W Karas
Guest
Posts: n/a

 07-23-2012
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[i] = BF_GET(unsigned, v, Map_bf, u.fa[i]);
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[i], va[i])
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[i] = BF_GET(unsigned, v, Map_bf, u.fa[i]);
v3 = BF_GET(unsigned, v, Map_bf, f3);

v = 0;

for (i = 0; i < 4; ++i)
BF_OR(v, Map_bf, u.fa[i], va[i])
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);
}

Ike Naar
Guest
Posts: n/a

 07-23-2012
On 2012-07-23, W Karas <(E-Mail Removed)> 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?

wkaras@yahoo.com
Guest
Posts: n/a

 07-23-2012

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

Jorgen Grahn
Guest
Posts: n/a

 07-24-2012
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 .