Reputation: 3383
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
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
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
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
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
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