How to form a 64-bit number using 2 pointers?

Suppose I have two pointers

uint64_t* ptr1;
uint64_t* ptr2;

      

I need to form the var value so that 6 bytes are taken from ptr1 and 2 bytes from ptr2 and currently ptr1 is consuming its initial 2 bytes and now the remaining bytes left to process are 6 bytes.

I wrote something like this

uint64_t value = (uint64_t)((*ptr1) >> 16);\
value = (uint64_t)(value << 16 | (*ptr2 & 0x000000000000ffff));\

      

Ideally, its mask should be 0xffff000000000000, but it doesn't work. (For processing purposes). How do I proceed and what am I doing wrong here? For me it should be easy

value = (uint64_t)((*ptr1 & ~0x000000000000ffff)  << 16 | (*ptr2 & 0xffff000000000000));

      

EDIT: ptr1 here points to (uint8_t *) ptr1 +2 i.e. 2 bytes after ptr1

+3


source to share


4 answers


First write the mask

#define mask 0xFFFFFFFFFFFF 

      

Extract 6 bytes from ptr1

and store them

const uint64_t first_six = *ptr1 & mask;

      

Extract 2 bytes from ptr2

and save them

const uint16_t last_two = *ptr2 & 0xFFFFull;

      



Finally, connect them

uint64_t value = (first_six << 16) | last_two;

      

In one expression

uint64_t value = ( (*ptr1 & mask) << 16 ) | (*ptr2 & 0xFFFFull);

      

I also wanted to know if endianness matters during disguise?

In this case, the Endianness value is irrelevant.

+1


source


I'm not really sure what you are trying to do here, your question is somewhat vague ... but I will try as I understand it:

Your last line

value = (uint64_t)((*ptr1 & ~0x000000000000ffff)  << 16 | (*ptr2 & 0xffff000000000000));

      

does this: it extracts the top 48 bits of * ptr1 and multiplies the result by 2 ^ 16. The result is a number containing the middle 32 bits of * ptr1, shifted by the top 32 bits. Then you extract the top 16 bits from * ptr2 and / or for that first value. Your result will be in the upper 32 bits of the combined value, with bits from * ptr2 going directly or bits from * ptr1. You probably want to do something like this:

value = (uint64_t)((*ptr1  >> 16) | (*ptr2 & 0xffff000000000000));

      



which would combine the low 48 bits * ptr1 with the high 16 bits * ptr2, or

value = (uint64_t)((*ptr1 & ~0x000000000000ffff) | (*ptr2 & 0x000000000000ffff));

      

which combines high 48 bits * ptr1 with low 48 bits * ptr2, or maybe even

value = (uint64_t)((*ptr1  >> 16) | (*ptr2 & 0x000000000000ffff) << 48);

      

which puts the top 48 bits * ptr1 at the bottom of the new value, and the bottom 16 bits * ptr2 in the top 16 bits of the result.

0


source


(uint64_t)((*ptr1 & ~0x000000000000ffff)  << 16 | (*ptr2 & 0xffff000000000000));

      

Taken an expression at a time:

(*ptr1 & ~0x000000000000ffff)   

      

leads to 12 34 56 78 9a bc 00 00

12 34 56 78 9a bc 00 00  << 16 

      

leads to 56 78 9a bc 00 00 00 00

(*ptr2 & 0xffff000000000000)) 

      

leads to 12 34 00 00 00 00 00 00

56 78 9a bc 00 00 00 00 | 12 23 00 00 00 00 00 00 

      

leads to ?? ?? 9a bc 00 00 00 00

which doesn't add the first 6 bytes *ptr1

with the last 2 bytes*ptr2

I suggest

(uint64_t)((*ptr1 & ~0x000000000000ffff)  | (*ptr2 & 0x000000000000ffff));

      

0


source


The OP is wrongly trying to make the 64-bit mask too narrow a constant.

On a less than 64-bit machine, int/unsigned

0x000000000000ffff

there is a width constant of "less than 64". On a 32-bit machine ~0x000000000000ffff

0xffff0000

, rather than waiting0xffffffffffff0000

The addition LL

ensures that the constant is at least 64-bit.

To implement "form is var so that 6 bytes come from ptr1 and 2 bytes from ptr2"

#define BYTES7TO2_MASK (0xffffffffffff0000)
#define BYTES1TO0_MASK (0xffff)
value = ((*ptr1 & BYTES7TO2_MASK) >> 16) || ((*ptr2 & BYTES1TO0_MASK) << (64-16));

      

0


source







All Articles