通过指向具有 C 中位字段的结构的指针访问无符号整数的各个位

Accessing individual bits of unsigned integer through pointer to struct with bit fields in C

假设我们有一个定义如下的结构:

struct S_BF {
    unsigned first_bit : 1;
    unsigned second_bit : 1;
    unsigned rest : 30;
}

和指向 S_BF 结构的指针:

struct S_BF*  bf;

如果我们有一个变量:

unsigned int p = 0;

如何让bf指向p,这样我们就可以通过修改它的位域来修改p的值,例如,如果我们想改变p的值p 到 2,我们可以这样做:

bf->second_bit = 1;

想要使用 struct S_BF* 类型的指针访问 unsigned p 的位的问题是它违反了 strict alias 规则 C11 Standard - §6.5 Expressions (p6,7).该规则旨在防止使用指向另一种类型的指针访问一种类型的对象。 (有各种例外,但规则的目的是防止指针的类型双关)

通过指向 struct S_BF 的指针访问 unsigned 的位的唯一符合标准的方法,它通过 struct S_BF 之间的 union 使这些位相同] 和 unsigned。您必须可以通过指向 struct S_BF 的指针访问 struct S_BF 的位,并在不违反字符串别名规则的情况下通过联合使 struct S_BFunsigned 相同。一个简短的例子是:

#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');
}

例子Use/Output

以上示例将产生以下输出:

$ ./bin/bitfield_union
10101010101010101010101010101010