Доступ к отдельным битам целого без знака через указатель на структуру с битовыми полями в C - PullRequest
0 голосов
/ 12 октября 2019

Допустим, у нас есть структура, определенная как:

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

И указатель на S_BF struct:

struct S_BF*  bf;

Если у нас есть переменная:

unsigned int p = 0;

Как мы можем заставить bf указывать на p, чтобы мы могли изменить значение p, изменив его битовые поля, например, если мы хотим изменить значение p на 2, мыможно сделать это:

bf->second_bit = 1;

1 Ответ

0 голосов
/ 12 октября 2019

Проблема с желанием получить доступ к битам unsigned p с указателем типа struct S_BF* состоит в том, что он нарушает строгий псевдоним правило C11 Стандарт - §6.5 Выражения (p6,7) . Правило предназначено для предотвращения доступа к объекту одного типа с помощью указателя на другой. (Существуют различные исключения, но цель этого правила состоит в том, чтобы предотвратить наложение указателей на типы)

Единственный стандартный соответствующий способ доступа к битам unsigned через указатель на struct S_BF itсделать биты одинаковыми битами через union между struct S_BF и unsigned. Вы должны получить доступ к битам struct S_BF через указатель на struct S_BF и сделать struct S_BF и unsigned одинаковыми через объединение, не нарушая правила псевдонимов строк. Коротким примером будет:

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

Пример использования / вывода

Приведенный выше пример приведет к следующему выводу:

$ ./bin/bitfield_union
10101010101010101010101010101010
...