Let's say we have a struct defined like:
struct S_BF {
unsigned first_bit : 1;
unsigned second_bit : 1;
unsigned rest : 30;
}
And a pointer to S_BF
struct:
struct S_BF* bf;
If we have a variable:
unsigned int p = 0;
How can we make bf
point to p
so we can modify the value of p
by modifying its bit fields, for example, if we want to change the value of p
to 2, we can do this:
bf->second_bit = 1;
The problem with wanting to access the bits of unsigned p
with a pointer of type struct S_BF*
is that it violates the strict alias rule C11 Standard - §6.5 Expressions (p6,7). The rule is designed to prevent accessing an object of one type by using a pointer to another. (there are various exceptions, but the intent of the rule is to prevent the type-punning of pointers)
The only standard conforming way to access the bits of an unsigned
through a pointer to struct S_BF
it to make the bits the same bits through a union
between struct S_BF
and unsigned
. You must can access the bits of struct S_BF
through a pointer to struct S_BF
, and make the struct S_BF
and unsigned
the same through the union without violating the string aliasing rule. A short example would be:
#include <stdio.h>
struct S_BF { /* bitfield struct */
unsigned first_bit : 1;
unsigned second_bit : 1;
unsigned rest : 30;
};
union s2u { /* union bitfield struct/unsigned */
struct S_BF s;
unsigned u;
};
int main (void) {
union s2u s2u = { .u = 0 }; /* union initialized zero */
struct S_BF *bf = &s2u.s; /* pointer to bitfield */
unsigned sz = 32; /* no. of bits in unsigned */
bf->second_bit = 1; /* set second bit 1 */
bf->rest = 0x2aaaaaaa; /* alternating bits 1010101... */
while (sz--) /* loop sz times, using unsigned value in union */
putchar (s2u.u >> sz & 1 ? '1' : '0'); /* output bits */
putchar ('\n');
}
Example Use/Output
The above example would result in the following output:
$ ./bin/bitfield_union
10101010101010101010101010101010