#include struct BF { unsigned char a : 1; unsigned char b : 2; unsigned char c : 5; }; unsigned char noBF = 0; //#define C #undef C #ifdef C /* Note the absence of defensive programming such as checking to ensure that byte is not null and that bit_number is not too large. */ void ClearA(unsigned char * byte) { *byte &= ~1; } void SetA(unsigned char * byte) { *byte &= ~1; *byte |= 1; } void ClearB(unsigned char * byte) { *byte &= ~6; } void SetB(unsigned char * byte, unsigned char value) { value &= 3; // ensures only bits 0 and 1 can be set *byte &= ~6; // clears bits 1 and 2 in byte *byte |= (value << 1); // stores bits 0 and 1 into bits 2 and 3 } void ClearC(unsigned char * byte) { *byte &= 7; // squashes bits 3 to 7 to 0 } void SetC(unsigned char * byte, unsigned char value) { value &= 0x1F; // ensures only bits 0 to 4 can be set *byte &= ~(0x1F << 3); // squashes correct bits in byte *byte |= (value << 3); // or's in the bits at the right place } #else extern void SetA(unsigned char *); extern void SetB(unsigned char *, unsigned char); extern void SetC(unsigned char *, unsigned char); extern void ClearA(unsigned char *); extern void ClearB(unsigned char *); extern void ClearC(unsigned char *); #endif int main() { volatile struct BF bf; bf.a = 1; bf.b = 2; bf.c = 3; SetA(&noBF); SetB(&noBF, 2); SetC(&noBF, 3); printf("noBF should be 0x1D - value: 0x%X\n", (unsigned int) noBF); printf("bf should be 0x1D - value: 0x%X\n", (unsigned int) *((unsigned char *) &bf)); return 0; }