Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert BYTE array into unsigned long long int

Tags:

c++

I'm trying to convert a BYTE array into an equivalent unsigned long long int value but my coding is not working as expected. Please help with fixing it or suggest an alternative method for the same.

Extra Information: These 4 bytes are combined as a hexadecimal number and an equivalent decimal number is an output. Say for a Given byteArray= {0x00, 0xa8, 0x4f, 0x00}, Hexadecimal number is 00a84f00 and it's equivalent decimal number is 11030272.

#include <iostream>
#include <string>

typedef unsigned char BYTE;

int main(int argc, char *argv[])
{
  BYTE byteArray[4] = { 0x00, 0x08, 0x00, 0x00 };
  std::string str(reinterpret_cast<char*>(&byteArray[0]), 4);
  std::cout << str << std::endl;

  unsigned long long ull = std::strtoull(str.c_str(), NULL, 0);
  printf ("The decimal equivalents are: %llu", ull);


  return EXIT_SUCCESS;
}

I'm getting the following output:

The decimal equivalents are: 0

While the expected output was:

The decimal equivalents are: 2048
like image 298
user9059547 Avatar asked Jan 28 '23 18:01

user9059547


2 Answers

When you call std::strtoull(str.c_str(), NULL, 0);, its first argument supplied is equivalent to an empty string, as string is essentially a null-terminated sequence of characters.

Second, std::strtoull() does not convert with byte sequences, it converts with the literal meaning of strings. i.e. you'll get 2048 with std::strtoull("2048", NULL, 10).

Another thing to note is that unsigned long long is a 64-bit data type, whereas your byte array only provides 32 bits. You need to fill the other 32 bytes with zero to get the correct result. I use a direct assignment, but you could also use std::memset() here.

What you want to do is:

ull = 0ULL;
std::memcpy(&ull, byteArray, 4);

Given your platform has little-endian, the result should be 2048.

like image 104
iBug Avatar answered Jan 31 '23 08:01

iBug


What you first must remember is that a string, is really a null-terminated string. Secondly, a string is a string of characters, which is not what you have. The third problem is that you have an array of four bytes, which corresponds to an unsigned 32-bit integer, and you want an (at least) 64-bit types which is 8 bytes.

You can solve all these problems with a temporary variable, a simple call to std::memcpy, and an assignment:

uint32_t temp;
std::memcpy(&temp, byteArray, 4);
ull = temp;

Of course, this assumes that the endianness is correct.


Note that I use std::memcpy instead of std::copy (or std::copy_n) because std::memcpy is explicitly mentioned to be able to bypass strict aliasing this way, while I don't think the std::copy functions are. Also the std::copy functions are more for copying elements and not anonymous bytes (even if they can do that too, but with a clunkier syntax).

like image 24
Some programmer dude Avatar answered Jan 31 '23 07:01

Some programmer dude