Reputation: 77
let's say that i have 8 unsigned char, that i want to convert to an unsigned long long.
for example, if all char are equals to 0xFF, the unsigned long long would be equal to 0xFFFFFFFFFFFFFFFF.
what's the most efficient way to do that with C or C++?
Upvotes: 5
Views: 7635
Reputation: 4891
Sorry about my initial silly answer, really should have read the question more carefully. Hopefully this one is more helpful. The way you convert depends on whether the endianness of the long long representation in the byte array matches that of the architecture you are working on.
C++:
#include <iostream>
#include <cstring>
using namespace std;
// Assuming ca is at least 8 bytes, the size of long long, interpret the
// first 8 bytes as long long.
// differentEndian == true means the endianness of the machine is
// different from the representation in ca.
long long getLongLong( unsigned char * ca, bool differentEndian )
{
long long retVal;
if (differentEndian)
{
for (int i = 0; i < 4; i++)
{
unsigned char _tmpCh = ca[i];
ca[i] = ca[7-i];
ca[7-i] = _tmpCh;
}
}
retVal = *reinterpret_cast<unsigned long long *>(ca);
return retVal;
}
int main()
{
unsigned char cArray[] = {0xff, 0x1, 0x70, 0x2, 0x61, 0x3, 0x52, 0x4};
unsigned long long ll = getLongLong( cArray, false );
cout << "Result for same endian: " << hex << ll << " or " << dec << ll << endl;
ll = getLongLong( cArray, true );
cout << "Result for different endian: " << hex << ll << " or " << dec << ll << endl;
return 0;
}
C:
#include <stdio.h>
#include <string.h>
// Assuming ca is at least 8 bytes, the size of long long, interpret the
// first 8 bytes as long long.
// differentEndian != 0 means the endianness of the machine is
// different from the representation in ca.
long long getLongLong( unsigned char * ca, int differentEndian )
{
long long retVal;
if (differentEndian)
{
int i;
for (i = 0; i < 4; i++)
{
unsigned char _tmpCh = ca[i];
ca[i] = ca[7-i];
ca[7-i] = _tmpCh;
}
}
memcpy( &retVal, ca, sizeof(long long));
return retVal;
}
int main()
{
unsigned char cArray[] = {0xff, 0x1, 0x70, 0x2, 0x61, 0x3, 0x52, 0x4};
unsigned long long ll = getLongLong( cArray, 0 );
printf("Result for same endian: %llx or %llu\n", ll, ll);
ll = getLongLong( cArray, 1 );
printf("Result for different endian: %llx or %llu\n", ll, ll);
return 0;
}
The output from both versions is:
Result for same endian: 4520361027001ff or 311315039429591551
Result for different endian: ff01700261035204 or 1837509111016818739
Upvotes: 0
Reputation: 5694
Instead of memcpy, you can directly assign the bits
unsigned char buffer[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned long long l = 0;
for (int i = 0; i < 8; ++i) {
l = l | ((unsigned long long)buffer[i] << (8 * i));
}
I believe this is immune to endianness.
Upvotes: 5
Reputation: 263617
For example:
unsigned char buffer[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
unsigned long long target;
memcpy(&target, buffer, sizeof target);
Note that if not all the elements of buffer
have the same value, the result will depend on byte ordering (little-endian vs. big-endian).
This also assumes that unsigned long long
is exactly 8 bytes. That's very commonly true, but it's not guaranteed. (It's also not guaranteed that a byte is exactly 8 bits; it can be more. An unsigned char
is by definition 1 byte.)
Upvotes: 6