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
source to share
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.
source to share
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.
source to share
(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));
source to share
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));
source to share