Вывести полное uint32_t в шестнадцатеричном виде из структуры bitfield - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть структура, подобная приведенной ниже:

struct myCoolStuff{
    uint32_t stuff1 :  4;
    uint32_t stuff2 :  4;
    uint32_t stuff3 : 24;
    uint32_t differentField;
}

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

struct myCoolStuff data = {.stuff1=0xFF, .stuff2=0x66, .stuff3=0x112233, .differentField=99};

printf("my combined stuff is: %x\n", <combined stuff>);
printf("My full field is: %x\n", data.differentField);

Expected Output: 
my combined stuff is: 0xFF66112233 
My different field is: 99

Ответы [ 4 ]

0 голосов
/ 20 ноября 2018

Умножьте (используя не менее uint32_t математические), а затем напечатайте, используя соответствующий спецификатор.

#include <inttypes.h>

struct myCoolStuff{
    uint32_t stuff1 :  4;
    uint32_t stuff2 :  4;
    uint32_t stuff3 : 24;
    uint32_t differentField;
}

uint32_t combined stuff = ((uint32_t) data.stuff1 << (4 + 24)) | 
    ((uint32_t) data.stuff2 <<  24) |  data.stuff3;

printf("my combined stuff is: 0x%" PRIX32 "\n", combined stuff);
printf("My full field is: %x\n", data.differentField);
0 голосов
/ 20 ноября 2018

Может быть, что-то вроде этого поможет:

unsigned char *ptr = (unsigned char *)&data; // store start address
int size = sizeof(myCoolStuff); // get size of struct in bytes
while(size--) // for each byte
{
    unsigned char c = *ptr++; // get byte value
    printf(" %x ", (unsigned)c); // print byte value
}
0 голосов
/ 20 ноября 2018

Во-первых, вы не можете получить 0xFF из 0xFF после помещения его в 4-битную переменную.0xFF занимает 8 бит.То же самое для 0x66.

Что касается реинтерпретации битовых полей как единого целого числа, вы могли бы, в очень непереносимом стиле (есть проблемы с прямым порядком байтов / прямым порядком байтов и возможностьюбиты заполнения) используйте union.

(Это:

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

struct myCoolStuff{
    union{
        struct {
        uint32_t stuff1 :  4;
        uint32_t stuff2 :  4;
        uint32_t stuff3 : 24;
        };
        uint32_t fullField;
    };
};
struct myCoolStuff data = {.stuff1=0xFF, .stuff2=0x66, .stuff3=0x112233};

int main()
{
    printf("My full field is: %" PRIX32 "\n", data.fullField);
}

печатает 1122336F на моем x86_64.)

Для этого переносимо Вы можете просто взять битовые поля и соединить их вручную:

Это:

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

struct myCoolStuff{
        uint32_t stuff1 :  4;
        uint32_t stuff2 :  4;
        uint32_t stuff3 : 24;
};
struct myCoolStuff data = {.stuff1=0xFF, .stuff2=0x66, .stuff3=0x112233};

int main()
{
    uint32_t fullfield = data.stuff1 << 28 | data.stuff2 << 24 | data.stuff3;
    printf("My full field is: %" PRIX32 "\n", fullfield);
}

должно печатать F6112233 в любом месте, где он компилируется (uint32_t не гарантированно существует(хотя на платформах POSIX это будет); uint_least32_t было бы более переносимым.)

Будьте внимательны, чтобы убедиться, что data.stuff1 имеет достаточно битов, чтобы их можно было сдвинуть на 28.Ваш делает, потому что он набрал uint32_t, но было бы безопаснее сделать это, например, с (data.stuff1 + 0UL)<<28 или (data.stuff1 + UINT32_C(0))<<28 и то же самое для второй смены.

0 голосов
/ 20 ноября 2018

Добавьте объединение внутри этой структуры, которое вы можете использовать для переинтерпретации полей.

struct myCoolStuff{
    union {
        struct {
            uint32_t stuff1 :  4;
            uint32_t stuff2 :  4;
            uint32_t stuff3 : 24;
        };
        uint32_t stuff;
    }
    uint32_t fullField;
};

...

printf("my combined stuff is: %x\n", data.stuff);
...