简体   繁体   中英

how do i convert an unsigned char array into an unsigned long long?

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++?

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.)

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM