Преобразование битового поля в int - PullRequest
13 голосов
/ 18 марта 2010

У меня битовое поле объявлено так:

typedef struct morder {
    unsigned int targetRegister : 3;
    unsigned int targetMethodOfAddressing : 3;
    unsigned int originRegister : 3;
    unsigned int originMethodOfAddressing : 3;
    unsigned int oCode : 4;
} bitset;

У меня также есть массив int, и я хочу получить значение int из этого массива, которое представляет фактическое значение этого битового поля (которое на самом деле является неким машинным словом, которое у меня есть, и я хочу int представление всего слова).

Большое спасибо.

Ответы [ 3 ]

20 голосов
/ 18 марта 2010

Пожалуйста, пожалуйста, не используйте союз. Или, скорее, понять, что вы делаете, используя союз - предпочтительно, прежде чем использовать его.

Как видно из этого ответа , не полагайтесь на то, что битовые поля переносимы. Специально для вашего случая упорядочение битовых полей в структуре зависит от реализации.

Теперь, если ваш вопрос был, как вы можете распечатать структуру битовых полей как int, для периодического частного просмотра, конечно, объединения хороши. Но вам, кажется, нужно «фактическое значение» ваших битовых полей.

Итак: если вы работаете только с этой одной комбинацией машина / компилятор, и вам не нужно полагаться на математическое значение типа int, если это имеет смысл, вы можете использовать объединения , Но если вы можете портировать свой код или вам нужно «фактическое значение» int, вам нужно написать код для управления битами, чтобы получить битовые поля в правильные биты int.

15 голосов
/ 18 марта 2010

Вы можете использовать союз:

typedef union bitsetConvertor {
    bitset bs;
    uint16_t i;
} bitsetConvertor;

bitsetConvertor convertor;
convertor.i = myInt;
bitset bs = convertor.bs;

Или вы можете использовать приведение:

bitset bs = *(bitset *)&myInt;

Или вы можете использовать анонимную структуру внутри объединения:

typedef union morder {
    struct {
        unsigned int targetRegister : 3;
        unsigned int targetMethodOfAddressing : 3;
        unsigned int originRegister : 3;
        unsigned int originMethodOfAddressing : 3;
        unsigned int oCode : 4;
    };

    uint16_t intRepresentation;
} bitset;

bitset bs;
bs.intRepresentation = myInt;
4 голосов
/ 18 марта 2010

Конечно - просто используйте союз. Затем вы можете получить доступ к своим данным как 16-битное целое или как отдельные битовые поля, например,

#include <stdio.h>
#include <stdint.h>

typedef struct {
    unsigned int targetRegister : 3;
    unsigned int targetMethodOfAddressing : 3;
    unsigned int originRegister : 3;
    unsigned int originMethodOfAddressing : 3;
    unsigned int oCode : 4;
} bitset;

typedef union {
    bitset b;
    uint16_t i;
} u_bitset;

int main(void)
{
    u_bitset u = {{0}};

    u.b.originRegister = 1;
    printf("u.i = %#x\n", u.i); 

    return 0;
}
...