Skip to content

Instantly share code, notes, and snippets.

@OrangeTide
Created April 7, 2011 17:47
Show Gist options
  • Save OrangeTide/908295 to your computer and use it in GitHub Desktop.
Save OrangeTide/908295 to your computer and use it in GitHub Desktop.
bitfield macros
/* bitfield.h - bitfield macros */
/*
* PUBLIC DOMAIN - NO COPYRIGHT CLAIMED - Jonathan Mayo - July 2005
*
* Updated January 2010
*/
#ifndef BITFIELD_H
#define BITFIELD_H
#include <limits.h>
/* return in type sized elements to create a bitfield of 'bits' bits */
#define BITFIELD(bits, type) (((bits)+(CHAR_BIT*sizeof(type))-1)/(CHAR_BIT*sizeof(type)))
/* size of a word */
#define BITWORDSZ(x) (CHAR_BIT*sizeof *(x))
/* set bit position 'bit' in bitfield x */
#define BITSET(x, bit) (x)[(bit)/(BITWORDSZ(x))]|=1ul<<((bit)%BITWORDSZ(x))
/* clear bit position 'bit' in bitfield x */
#define BITCLR(x, bit) (x)[(bit)/(BITWORDSZ(x))]&=~(1ul<<((bit)%BITWORDSZ(x)))
/* toggle bit position 'bit' in bitfield x */
#define BITINV(x, bit) (x)[(bit)/(BITWORDSZ(x))]^=1ul<<((bit)%BITWORDSZ(x))
/* return a large non-zero number if the bit is set, zero if clear */
#define BITTEST(x, bit) ((x)[(bit)/(BITWORDSZ(x))]&(1ul<<((bit)%BITWORDSZ(x))))
/* checks that bit is in range for bitfield x.
* doesn't work if x is a pointer, must be an array. */
#define BITRANGE(x, bit) ((bit)<(sizeof(x)*CHAR_BIT))
/* example/test program
#include <stdio.h>
#include <stdlib.h>
#include "bitfield.h"
int main(int argc, char **argv) {
unsigned long bits[BITFIELD(100,unsigned long)] = {0};
int i;
printf("size=%d bytes (%d bits)\n",sizeof bits, CHAR_BIT * sizeof bits);
for(i=1;i<argc;i++) {
unsigned f;
f=strtoul(argv[i], 0, 0);
BITSET(bits, f);
}
for(i=0;i<(sizeof bits/sizeof *bits);i++) {
printf("bits[%d]=0x%08lX\n", i, bits[i]);
}
return 0;
}
*/
#endif
/* bitfield_test.c : PUBLIC DOMAIN - Jon Mayo - July 2005
* - You may remove any comments you wish, modify this code any way you wish,
* and distribute any way you wish.*/
/* example of using bitfield.h macros */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bitfield.h"
#define NR(x) (sizeof(x)/sizeof*(x))
static void dump_bits(unsigned long *bits, unsigned bitcnt) {
unsigned a;
for(a=0;a<bitcnt;a++) {
if(a && a%BITWORDSZ(bits)==0) printf(":");
if(a && a%BITWORDSZ(bits)==BITWORDSZ(bits)/2) printf(".");
printf("%u", !!BITTEST(bits, a));
}
printf("\n");
}
static void dump_words(unsigned long *bits, unsigned bitcnt) {
unsigned a;
for(a=0;a<bitcnt/BITWORDSZ(bits);a++) {
printf("0x%lx ", bits[a]);
}
printf("\n");
}
static void dump_ranges(unsigned long *bits, unsigned bitcnt) {
unsigned a, b, n;
for(a=0,n=0;a<bitcnt;a++) {
if(BITTEST(bits, a)) {
if(n) printf(",");
for(b=a+1;b<bitcnt && BITTEST(bits, b);b++) ;
b--;
if(a==b)
printf("%u", a);
else
printf("%u-%u", a, b);
a=b;
n++;
}
}
printf("\n");
}
static void dump(unsigned long *bits, unsigned bitcnt) {
printf("ranges = ");
dump_ranges(bits, bitcnt);
printf("words = ");
dump_words(bits, bitcnt);
printf("bits = ");
dump_bits(bits, bitcnt);
}
int generic_test() {
unsigned long f[BITFIELD(300, unsigned long)];
printf("size=%u bytes (%u bits)\n",(unsigned)sizeof f, (unsigned)(CHAR_BIT * sizeof f));
memset(f, 0, sizeof f);
BITINV(f, 0);
dump(f, NR(f)*BITWORDSZ(f));
BITCLR(f, 0);
dump(f, NR(f)*BITWORDSZ(f));
BITINV(f, 0);
BITINV(f, 32);
BITSET(f, 3);
BITSET(f, 4);
BITSET(f, 5);
BITSET(f, 43);
BITSET(f, 44);
BITSET(f, 45);
BITSET(f, 81);
BITSET(f, 95);
BITSET(f, 96);
BITSET(f, 97);
dump(f, NR(f)*BITWORDSZ(f));
return 0;
}
/* pass a list of numbers to set in the bitfield. we choose to make 100-bit
* value, rounded up to the nearest unsigned long size. */
int main(int argc, char **argv) {
unsigned long bits[BITFIELD(100,unsigned long)] = {0};
unsigned i;
/* run an automatic test if no arguments specified. */
if(argc==1) return generic_test();
printf("size=%u bytes (%u bits)\n",(unsigned)sizeof bits, (unsigned)(CHAR_BIT * sizeof bits));
for(i=1;i<(unsigned)argc;i++) {
unsigned f;
f=strtoul(argv[i], 0, 0);
BITSET(bits, f);
}
for(i=0;i<(sizeof bits/sizeof *bits);i++) {
printf("bits[%d]=0x%08lX\n", i, bits[i]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment