CherryQu
CherryQu

Reputation: 3383

How to convert a 48-bit byte array into an 64-bit integer in C?

I have an unsigned char array whose size is 6. The content of the byte array is an integer (4096*number of seconds since Unix Time). I know that the byte array is big-endian.

Is there a library function in C that I can use to convert this byte array into int_64 or do I have to do it manually?

Thanks!

PS: just in case you need more information, yes, I am trying to parse an Unix timestamp. Here is the format specification of the timestamp that I dealing with.

Upvotes: 4

Views: 5043

Answers (5)

vpatial
vpatial

Reputation: 33

Here is a method to convert it to 64 bits:

uint64_t
convert_48_to_64(uint8_t *val_ptr){
  uint64_t ret = 0;
  uint8_t *ret_ptr = (uint8_t *)&ret;

  for (int i = 0; i < 6; i++) {
      ret_ptr[5-i] = val_ptr[i];
  }
  return ret;
 }

 convert_48_to_64((uint8_t)&temp);  //temp is in 48 bit

eg: num_in_48_bit = 77340723707904; this number in 48 bit binary will be : 0100 0110 0101 0111 0100 1010 0101 1101 0000 0000 0000 0000 After conversion in 64 bit binary will be : 0000 0000 0000 0000 0000 0000 0000 0000 0101 1101 0100 1010 0101 0111 0100 0110 let's say val_ptr stores the base address of num_in_48_bit. Since pointer typecast to uint8_t, incrementing val_ptr will give you next byte. Looping over and copy the value byte by byte. Note, I am taking care of network to byte order as well.

Upvotes: 0

phuclv
phuclv

Reputation: 41794

You can use pack option

#pragma pack(1)

or

__attribute__((packed))

depending on the compiler

typedef struct __attribute__((packed))
{
    uint64_t u48: 48;
} uint48_t;

uint48_t data;

memcpy(six_byte_array, &data, 6);
uint64_t result = data.u48;

See

Upvotes: -1

jpdevillers
jpdevillers

Reputation: 7

I think the best way to do it is using a union.

union time_u{
    uint8_t data[6];
    uint64_t timestamp;
}

Then you can use that memory space as a byte array or uint64_t, by referencing

union time_u var_name;
var_name.data[i]
var_name.timestamp

Upvotes: 0

Samy Arous
Samy Arous

Reputation: 6814

Have your tried this:

unsigned char a [] = {0xaa,0xbb,0xcc,0xdd,0xee,0xff};
unsigned long long b = 0;
memcpy(&b,a,sizeof(a)*sizeof(char));
cout << hex << b << endl;

Or you can do it by hand which will avoid some architecture specific issues.

I would recommend using normal integer operation (sums and shifts) rather than trying to emulate memory block ordering which is no better than the solution above in term of compatibility.

Upvotes: 0

dreamlax
dreamlax

Reputation: 95335

A C99 implementation may offer uint64_t (it doesn't have to provide it if there is no native fixed-width integer that is exactly 64 bits), in which case, you could use:

#include <stdint.h>

unsigned char data[6] = { /* bytes from somewhere */ };
uint64_t result = ((uint64_t)data[0] << 40) |
                  ((uint64_t)data[1] << 32) |
                  ((uint64_t)data[2] << 24) |
                  ((uint64_t)data[3] << 16) |
                  ((uint64_t)data[4] << 8)  |
                  ((uint64_t)data[5] << 0);

If your C99 implementation doesn't provide uint64_t you can still use unsigned long long or (I think) uint_least64_t. This will work regardless of the native endianness of the host.

Upvotes: 8

Related Questions