Как я могу объединить целочисленные битовые поля в c в целое число uint64_t? - PullRequest
0 голосов
/ 18 марта 2020

У меня есть структура в c, подобная этой

struct RegisterStruct
{
    uint64_t b_0 : 64;
    uint64_t b_1 : 64;
    uint64_t c_0 : 64;
    uint64_t c_1 : 64;
    uint64_t c_2 : 64;
    uint64_t d_0 : 64;
    uint64_t d_1 : 64;
};

Я хотел бы объединить поля в uint64_t целое число. Каждое из полей должно занимать определенное количество битов, определенных следующим образом:

b_0: 4bits 
b_1: 4bits
c_0: 8bits
c_1: 8bits
c_2: 8bits
d_1: 16bits
d_2: 16bits

Результатом должно быть целое число uint64_t, содержащее объединенные битовые поля (от b_0 до d_2), каждое из которых занимает заданное количество бит.

Вот то, что я пробовал, но я не думаю, что это правильное решение:

struct RegisterStruct Register;

   Register.b_0 = 8;
   Register.b_1 = 8;
   Register.c_0 = 128;
   Register.c_1 = 128;
   Register.c_2 = 128;
   Register.d_0 = 32768;
   Register.d_1 = 32768;

   uint64_t reg_frame =Register.b_0<<60|Register.b_1<<56|Register.c_0<<48|Register.c_1<<40|Register.c_2<<32|Register.d_0<<16|Register.d_1;

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Вы можете поместить структуру, содержащую битовые поля, в объединение с полным 64-битным целым числом без знака, например так:

union RegisterUnion
    struct
    {
        uint64_t b_0 : 4;
        uint64_t b_1 : 4;
        uint64_t c_0 : 8;
        uint64_t c_1 : 8;
        uint64_t c_2 : 8;
        uint64_t d_0 : 16;
        uint64_t d_1 : 16;
    };
    uint64_t val;
};

Основная проблема с вышеприведенным заключается в том, что она не переносима . Стандарт C оставляет порядок, в котором битовые поля упаковываются в базовый тип их запоминающего устройства (в данном случае uint64_t), как решение, определяемое реализацией. Это полностью отделено от упорядочения байтов внутри многобайтового целого, то есть упорядочения байтов с прямым порядком байтов по сравнению с порядком байтов с прямым порядком байтов.

Кроме того, использование uint64_t в качестве базового типа битового поля может не быть поддержанным. Реализация требуется только для поддержки членов битовых полей типов _Bool, signed int и unsigned int (или их квалифицированных версий). Согласно пункту 5 проекта C11, пункт 6.7.2.1:

Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией _Bool, signed int, unsigned int или некоторого другого типа, определенного реализацией. Это зависит от реализации, разрешены ли типы атомов c.
0 голосов
/ 18 марта 2020
typedef union
{ 
    struct
    {
        uint64_t b_0 : 4;
        uint64_t b_1 : 4;
        uint64_t c_0 : 8;
        uint64_t c_1 : 8;
        uint64_t c_2 : 8;
        uint64_t d_0 : 16;
        uint64_t d_1 : 16;
    };
    uint64_t u64;
}R_t;


int main()
{

    R_t Register;

    Register.b_0 = 8;
    Register.b_1 = 8;
    Register.c_0 = 128;
    Register.c_1 = 128;
    Register.c_2 = 128;
    Register.d_0 = 32768;
    Register.d_1 = 32768;

    printf("%llx\n", (long long unsigned)Register.u64);
}

https://godbolt.org/z/_dYuz2

...