mehmed_ali343
mehmed_ali343

Reputation: 9

How to convert unsigned char* to unsigned long long int?

Does anyone know of a library that provides a function that performs this logic or perhaps a method to perform this logic?

I'm trying to convert:

unsigned char test[] = "\x00\x00\x56\x4b\x7c\x8a\xc5\xde";

to:

94882212005342 / 0x0000564b7c8ac5de

I'm aware I could loop over each individual byte in test and utilize sprintf to convert each byte to string and concatenate them into a buffer with strcat and convert the buffer string to unsigned long long via strtoull. However I'm looking for something more comprehensive and simple. Is there such a way?

Upvotes: 0

Views: 2481

Answers (4)

Lundin
Lundin

Reputation: 214920

Just for the record, you can just simply do this:

#include <stdio.h>
#include <inttypes.h>

int main(int argc, char *argv[])
{
    unsigned char test[] = "\x00\x00\x56\x4b\x7c\x8a\xc5\xde";
    uint64_t val=0;
    for(size_t i=0; i<8; i++)
      val |= (uint64_t)test[i] << (7-i)*8;
    printf("%" PRIu64 " %" PRIX64, val, val);
}

Upvotes: 0

klutt
klutt

Reputation: 31429

A fun BUT NOT RECOMMENDED way of doing this. If you want a proper solution, look at KamilCuk's answer

#include <stdio.h>
#include <string.h>

// Reverse an 8-byte array  
void rev(unsigned char *s) {
    unsigned char *end = s + 7; // Evil hard coded value

    while(s<end) {
        unsigned char tmp = *s;
        *s = *end;
        *end = tmp;
        s++;
        end--;
    }
}

int main(void) {
    unsigned char test[] = "\x00\x00\x56\x4b\x7c\x8a\xc5\xde";
    rev(test);                // Reverse the array
    long l;
    memcpy(&l, test, sizeof test);
    printf("%zx\n", l);
}

Note that the standard does not dictate the byte order. This is what works on MY machine. It will be the same on most machines, but if portability to other architectures is important to you. Don't even consider this.

However, since you're saying that the value is an address, I'd recommend using uintptr_t instead of long.

Upvotes: -1

KamilCuk
KamilCuk

Reputation: 141768

It's just maths.

unsigned char test[] = "\x00\x00\x56\x4b\x7c\x8a\xc5\xde";
unsigned long long num = 
     (unsigned long long)test[0] << 56 |
     (unsigned long long)test[1] << 48 |
     (unsigned long long)test[2] << 40 |
     (unsigned long long)test[3] << 32 |
     (unsigned long long)test[4] << 24 |
     (unsigned long long)test[5] << 16 |
     (unsigned long long)test[6] <<  8 |
     (unsigned long long)test[7] <<  0;

Remember to cast to type wide enough before shifting.

You have 8 values:

 { 0x00, 0x00, 0x56, 0x4b, 0x7c, 0x8a, 0xc5, 0xde }

which in the decimal is:

 0 0 86 75 124 138 197 222

and you want to have:

 94882212005342

which is:

  94882212005342 = 0*2^56 + 0*2^48 + 86*2^40 + 75*2^32 + 124*2^24 + 138*2^16 + 197*2^8 +  222*2^0

It's a mathematical operation. You could write ex test[0] * 72057594037927936ull but that's less readable then test[0] << 56.

Upvotes: 2

Luke
Luke

Reputation: 49

I have done something very similar with the use of memmove or memcpy functions https://www.tutorialspoint.com/c_standard_library/c_function_memmove.htm

    long long int var = 0; 
    memmove( &var, test, sizeof(var) );

Make sure to use the correct byte order of your system.

Upvotes: 1

Related Questions