1

I have the following variables.

uint8_t flags;
uint32_t token;

I need to write function that cobine them into one uint64_t, and than parse them back into two variables, one of uint8_t and one of uint32_t.

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

I tried to found something that doing the following, but most of what I found is convert two of the same to one bigger, like two uint32_t to one uint64_t

Thank You

Dan The Man
  • 1,835
  • 6
  • 30
  • 50
  • `(uint64_t)flags ^ !token` would be a combination. Try if it works. If not, you should clarfy what you mean with "combine". That can mean anything! – too honest for this site Jun 16 '16 at 13:02
  • Do you want to just store the uint8 and uint32 in a uint64 variable? – Rishikesh Raje Jun 16 '16 at 13:03
  • @Olaf: ok, the "combine" part is ambiguous, but it's clear from the rest of the sentence it has to be a two-way transformation (bijection). – vgru Jun 16 '16 at 15:48
  • @Groo: That was just an intentionally nonsense example, sorry you did not get it. It still leaves a lot of options (apart from that some minor research effort by OP would have shown at least some way; I'd care less if there was at least **some** code shown - as-is, it is just a request for code). – too honest for this site Jun 16 '16 at 18:57

2 Answers2

4

How about:

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

This puts the 8-bit field "above" the 32-bit one, i.e. the returned uint64_t has its bits arranged like this:

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

Bit numbers in decimal should be read downwards, bit 0 is on the far right (the LSB).

I'll leave convertBack() (which is a pretty bad name, both of these names are sub-optimal) to you. :)

unwind
  • 391,730
  • 64
  • 469
  • 606
  • In the Ascii art above, it seems like `flags` are at the wrong position, at bit 40 (and 10 bits wide). – vgru Jun 16 '16 at 15:50
  • 1
    @Groo Thanks, I totally screwed that one up. I first "drew" it way simpler, and then messed it up when I changed styles. Fixed now I hope, and also added field withs in parentheses for perhaps 1% more clarity. – unwind Jun 17 '16 at 07:27
0

You may organize the 64bit integer with:

  • low 8bit for flags,

  • following 32bit for token

So,

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

the convert it back

void convertBack(uint64_t allTogether, uint8_t* flags, uint32_t* token)
{
    *flags = allTogether & ~( ~0UL << 8 );
    *token = allTogether >> 8;
}
artm
  • 17,291
  • 6
  • 38
  • 54