Convert array of 8 bytes to signed long in C++

14,089

Solution 1

You probably should use a int64_t which is guaranteeed to be 8 bytes long.

You don't state how your data is represented (its endianness) into your array but you might use reinterpret_cast<> or even better: use shift operations to "build" your integer.

Something like:

unsigned char array[8] = { /* Some values here */ };
uint64_t value = 
  static_cast<uint64_t>(array[0]) |
  static_cast<uint64_t>(array[1]) << 8 |
  static_cast<uint64_t>(array[2]) << 16 |
  static_cast<uint64_t>(array[3]) << 24 |
  static_cast<uint64_t>(array[4]) << 32 |
  static_cast<uint64_t>(array[5]) << 40 |
  static_cast<uint64_t>(array[6]) << 48 |
  static_cast<uint64_t>(array[7]) << 56;

Solution 2

Another way of conversion between data types, which I find convenient in some cases, is to use the union data type, which allows you to access the same memory portion as different data types. Of course all other remarks regarding endianness, size of data-types etc. still hold.

For example:

union bytes {
    unsigned char c[8];
    uint64_t l;
} myb;
myb.c[0] = 0;
myb.c[1] = 1;
myb.c[2] = 0;
myb.c[3] = 0;
myb.c[4] = 0;
myb.c[5] = 0;
myb.c[6] = 0;
myb.c[7] = 0;
cout << "value of myb.l: " << myb.l << "\n";

Solution 3

Why not just something like the following?

uint8_t start_arr[8] = {0,1,2,3,4,5,6,7};
uint64_t val = (uint64_t)(*(uint64_t*)&start_arr[0]);
std::cout << std::hex << val << std::endl;
Share:
14,089
Bob Bobbio
Author by

Bob Bobbio

Updated on June 04, 2022

Comments

  • Bob Bobbio
    Bob Bobbio about 2 years

    I have an array of 8 bytes and I'm trying to convert it to a signed long in C++, and can't seem to figure it out. From what I could tell long ints are only 4 bytes, can anybody provide some information on this? Is it going to matter if it is 32 or 64 bit?

    • Shamim Hafiz - MSFT
      Shamim Hafiz - MSFT over 13 years
      Post a bit more on what you want to achieve, possibly with an example.
    • littlegreen
      littlegreen over 13 years
    • Tony Delroy
      Tony Delroy over 13 years
      Though they're typically only available for 16 and 32 bit values, you might find some parallels with the "ntohl" family of functions. For Linux/GCC, they're implemented over bits/byteswap.h which also has __bswap_64, though that's all highly non-Standard it does illustrate use of the Intel's bswap assembly language instruction, and rorw/rorl for older CPUs. On FreeBSD, there's a sys/endian.h header.
  • aib
    aib over 13 years
    A long is at least 4 bytes long. It can be more. Much, much more.
  • ereOn
    ereOn over 13 years
    @aib: I'm using a uin64_t in my example, not a long. Why the downvote ?
  • littlegreen
    littlegreen over 13 years
    You did, but you changed your answer. Clever :)
  • aib
    aib over 13 years
    The 8-byte variant does not have to only exist on 64-bit systems.
  • aib
    aib over 13 years
    Can't undo the downvote yet. Unfortunately, stdint.h types are also C99-only.
  • jupp0r
    jupp0r over 8 years
    reinterpret_cast would violate strict aliasing rules and cause undefined behavior.
  • ereOn
    ereOn over 8 years
    @jupp0r: Despite what the standard says, I have yet to see a platform where using reinterpret_cast would not give the expected result in this case. I get your point, and agree on the theory but practicality often beats purity, and I believe this is such a case.
  • jupp0r
    jupp0r over 8 years
    @ereOn: While I agree with your general statement, average life time of code you write today is 10 years. Optimizers get better quite rapidly with all the innovation we see from LLVM and they could well be starting to rely on strict aliasing in the near future. Bugs introduced by this would be really hard to track down.
  • Mihai Andrei
    Mihai Andrei over 4 years
    Don't do this. This type punning is undefined behaviour. It will work if uint64_t has no alignment requirements (ex x86). If you do this disable strict aliasing in your compiler.
  • rial
    rial over 3 years
    how about std::int_fast64_t which is defined in the standard. There are fast and least versions depending on whether you value space or speed.