Reputation: 649
I have an 8-byte array in my application with this data:
00000133339e36a2
This data represents a long (on the platform the data was written in, on a Mac this would be a long long) with the value of
1319420966562
In the actual application this is a semi-randomized set of data, so the number will always be different. Therefore, I need to convert the byte array into a printable long long.
I've tried casting the data directly into a long long, but I came up with
1305392
where I should have been seeing the above number.
For those of you with more experience in C byte manipulation than I do, how would I correctly convert a byte array to a long long?
EDIT: Strangely, all of your solutions keep outputting the same number: 866006690. That is the decimal equivalent of the last four bytes of the data.
Upvotes: 7
Views: 11228
Reputation: 1
Perhaps a pointer notation?
uint8_t Array[8] = { 0x00,0x00,0x01,0x33,0x33,0x9e,0x36,0xa2 };
uint32_t *Long = Array;
Or if possible
*((uint32_t*)Array)
Upvotes: 0
Reputation: 41180
union le_long_long_array_u
{
uint8_t byte[8];
uint64_t longlong;
} le_long_long_array;
Copy (or just use) le_long_long_array.byte[]
for the array;
read back le_long_long_array.longlong
For example:
fill_array(&le_long_long_array.byte[0]);
return le_long_long_array.longlong;
Fuller example:
#include <stdint.h>
#include <stdio.h>
union le_long_long_array_u
{
uint8_t byte[8];
uint64_t longlong;
} le_long_long_array;
static uint8_t hex2int (char c)
{
return (c >= '0' && c <= '9')
? (uint8_t )(c - '0')
: ((c >= 'a' && c <= 'f')
? (uint8_t )(c - 'a')
: ((c >= 'A' && c <= 'F')
? (uint8_t )(c - 'A')
: 0));
}
int main (int argc, char **argv)
{
if (argc == 2)
{
int i;
for (i = 0; i <= 7; i++)
{
char *str = argv[1];
if (str[2*i] == '\0' || str[2*i+1] == '\0')
{
printf("Got short string.\n");
return 1;
}
le_long_long_array.byte[i] = (hex2int(str[2*i]) << 4) + hex2int(str[2*i+1]);
}
printf("Got %lld\n", le_long_long_array.longlong);
}
else
{
printf("Got %d args wanted 1.\n", argc - 1);
return 1;
}
return 0;
}
Produces:
e e$ gcc -c un.c
e e$ gcc -o un un.o
e e$ ./un 0100000000000000
Got 1
e e$ ./un 0101000000000000
Got 257
e e$ ./un a23639333301000000
Got 1319414347266
e e$
as you would expect for little endian data.
Upvotes: 4
Reputation: 1698
Great question! And great answers! To throw in a cent:
// Getting stuff "in"
unsigned long long ll1 = 1319420966562;
unsigned char * c = reinterpret_cast<unsigned char *>( &ll1 );
// Getting stuff "out"
unsigned long long ll2;
memcpy( &ll2, c, 8 );
ll2
is now equal to ll1
.
I must admin, however, I like the union
examples better. :)
Upvotes: 1
Reputation: 4557
Depending on your desired endianness, something like this would work:
int i;
char inArray[8] = { 0x00,0x00,0x01,0x33,0x33,0x9e,0x36,0xa2 };
long long outLong = 0;
for(i=0; i<8; i++)
outLong |= ( (long long)inArray[i]) << (i*8) );
Upvotes: 2
Reputation: 22979
This seems one of the (rare) situations where an union is useful:
union number
{
char charNum[16];
long long longNum;
};
Upvotes: 6
Reputation: 56059
long long num = 0;
for(int i = 0; i < 8; i++) {
num = (num << 8) | byte_array[i];
}
Assuming they're stored big-endian.
Upvotes: 2