Created
April 7, 2011 17:47
-
-
Save OrangeTide/908295 to your computer and use it in GitHub Desktop.
bitfield macros
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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