5

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

11
  • What if all chars are not equal to 0xFF? Commented Jan 14, 2016 at 1:50
  • You mean 0xFFFFFFFFFFFFFFFF? Commented Jan 14, 2016 at 1:50
  • 2
    Did you try *reinterpret_cast< unsigned long long * >( your_array ); Commented Jan 14, 2016 at 1:51
  • 1
    Which language, C or C++? The C language does not have reinterpret_cast. Commented Jan 14, 2016 at 1:52
  • 1
    big or little endian Commented Jan 14, 2016 at 1:57

3 Answers 3

6

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

Sign up to request clarification or add additional context in comments.

7 Comments

Using <stdint.h> or <cstdint> and uint64_t will always give 8 bytes.
@Jason: No, it will always give 64 bits, or 64 / CHAR_BIT bytes. But if you assume CHAR_BIT==8, then yes, uint64_t is always 8 bytes (if it exists!).
Very true, char isn't necessarily defined as a byte, which means a uint64_t may not hold the entire string. The size mismatch could be even worse with unsigned long long.
@Jason: No, a char is by definition one byte in C and C++. A byte is not necessarily an octet (8 bits); it can be bigger. unsigned long long is at least 64 bits, but can be bigger. On the other hand, systems with CHAR_BIT > 8 are rare (mostly DSPs), and I've never seen unsigned long long with a size other than exactly 64 bits.
I know signedness isn't defined for char, I didn't think it was actually defined as a byte though.
|
5

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.