конвертировать переменные uint8 и uint32 в одну uint64

У меня есть следующие переменные.

uint8_t flags;
uint32_t token;

Мне нужно написать функцию, которая объединяет их в один uint64_t, а затем анализирует их обратно на две переменные, одну из uint8_t и одну из uint32_t.

uint64 convert(uint8_t flags, uint32_t token);
void convertBack(uint64 allTogether, uint8_t* flags, uint32_t* token);

Я попытался найти что-то, что делает следующее, но большая часть того, что я нашел, это преобразование двух одинаковых в один большего размера, например двух uint32_t в один uint64_t

Благодарю вас


person daniel the man    schedule 16.06.2016    source источник
comment
(uint64_t)flags ^ !token будет комбинацией. Попробуйте, если получится. Если нет, вам следует уточнить, что вы имеете в виду под комбинацией. Это может означать что угодно!   -  person too honest for this site    schedule 16.06.2016
comment
Вы хотите просто сохранить uint8 и uint32 в переменной uint64?   -  person Rishikesh Raje    schedule 16.06.2016
comment
@Olaf: хорошо, часть объединения неоднозначна, но из остальной части предложения ясно, что это должно быть двустороннее преобразование (биекция).   -  person Groo    schedule 16.06.2016
comment
@Groo: Это был просто намеренно бессмысленный пример, извините, вы его не поняли. Это по-прежнему оставляет много вариантов (кроме того, что некоторые незначительные исследования OP показали бы хоть какой-то способ; меня бы не заботило, если бы был показан хотя бы какой-то код - как есть, это просто запрос кода).   -  person too honest for this site    schedule 16.06.2016


Ответы (2)


Как насчет:

uint64_t convert(uint8_t flags, uint32_t token)
{
  return ((uint64_t) flags << 32) | token;
}

Это помещает 8-битное поле «выше» 32-битного, т. е. возвращаемое uint64_t имеет свои биты, расположенные следующим образом:

 +---------------------------------+--------------------------------+
 |666655555555554444444444|33333333|3322222222221111111111          |
 |321098765432109876543210|98765432|10987654321098765432109876543210|
 +------------------------+--------+--------------------------------+
 |        unused(24)      |flags(8)|          token(32)             |
 +------------------------+-----------------------------------------+

Номера битов в десятичном формате следует читать вниз, бит 0 находится в крайнем правом углу (младший бит).

Я оставлю convertBack() (это довольно плохое имя, оба эти имени неоптимальны) вам. :)

person unwind    schedule 16.06.2016
comment
В изображении Ascii выше кажется, что flags находится в неправильном положении, на 40-м бите (и 10-битной ширине). - person Groo; 16.06.2016
comment
@Groo Спасибо, я полностью облажался. Сначала я нарисовал его проще, а потом испортил, когда сменил стили. Теперь исправлено, я надеюсь, а также добавлено поле с круглыми скобками, возможно, на 1% больше ясности. - person unwind; 17.06.2016

Вы можете организовать 64-битное целое число с помощью:

  • младшие 8 бит для flags,

  • следующие 32 бита для token

So,

uint64_t convert(uint8_t flags, uint32_t token)
{
    return ((uint64_t)token << 8) | flags;
}

преобразовать его обратно

void convertBack(uint64_t allTogether, uint8_t* flags, uint32_t* token)
{
    *flags = allTogether & ~( ~0UL << 8 );
    *token = allTogether >> 8;
}
person artm    schedule 16.06.2016