Home > Mobile >  How do I read a little-endian 64-bit value from a byte buffer?
How do I read a little-endian 64-bit value from a byte buffer?

Time:03-20

In a C application (not C ) I have a byte array of data received over the network. The array is 9 bytes long. The bytes 1 to 8 (zero-based) represent a 64-bit integer value as little endian. My CPU also uses little endian.

How can I convert these bytes from the array to an integer number?

I've tried this:

uint8_t rx_buffer[2000];
//recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, ...)
int64_t sender_time_us = *(rx_buffer   1);

But it gives me values like 89, 219, 234 or 27. The sender sees the values as 1647719702937548, 1647719733002117 or 1647719743790424. (These examples don't match, they're just random samples.)

CodePudding user response:

Unsafe solution:

int64_t sender_time_us = *(int64_t*)(rx_buffer   1);

This is potentially an alignment violation, and it's a strict aliasing rule violation. It's undefined behaviour. On some machines, this can kill your program with a bus error.


Safe solution:

int64_t sender_time_us;
memcpy( &sender_time_us, rx_buffer   1, sizeof( int64_t ) );

@Nate Eldredge points out that while this solution may look inefficient, a decent compiler should optimize this into something efficient. The net effect will be (a) to force the compiler to properly handle the unaligned access, if the target needs any special handling, (b) to make the compiler properly understand the aliasing and prevent any optimizations that would break it. For a target that is able to handle unaligned accesses normally, the generated code may not change at all.

CodePudding user response:

Your code is only getting a single uint8_t. You would need to cast to int64_t first. Something like this:

int64_t* pBuffer = (int64_t*)(rx_buffer   1);
int64_t sender_time_us = *pBuffer;

But you should be aware that some CPU's may not like to access 64-bit values that are not aligned. It may also be OK to this this if you know the endianess but it would actually be better to handle it in a more portable way.

CodePudding user response:

Tou need to cast your pointer, like so:

int64_t sender_time_us = *(int64_t*)(rx_buffer   1);

As it is, you're only getting one byte of data.

  • Related