3

How do i convert a vector of chars to a unsigned int 64?

std::vector<char> bytes = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x0b,0x52,0xed,0xfb,0x9f,0x29,0x80,0x00} qint64 wall_clock = (bytes.at(10) << 56 & 0xFF00000000000000) | (bytes.at(11) << 48 & 0x00FF000000000000) | (bytes.at(12) << 40 & 0x0000FF0000000000) | (bytes.at(13) << 32 & 0x000000FF00000000) | (bytes.at(14) << 24 & 0x00000000FF000000) | (bytes.at(15) << 16 & 0x0000000000FF0000) | (bytes.at(16) << 8 & 0x000000000000FF00) | (bytes.at(17) & 0x00000000000000FF); 

I keep getting 0xFFFF9F298000. the result should be 0x0B52EDFB9F298000.

what am i missing?

1 Answer 1

5

The shift operator promotes char to a 32-bit int (with sign extension on platforms with signed plain char) and shifting it beyond 31 bit is undefined behaviour.

You need to cast char to unsigned char first to avoid the sign extension, then cast it to uint64_t and only then do the shift:

static_cast<uint64_t>(static_cast<unsigned char>(bytes.at(10))) << 56 

Alternatively, just reverse copy it:

uint64_t load_bigendian(void const* bytes) { uint64_t result; std::copy( static_cast<unsigned char const*>(bytes), static_cast<unsigned char const*>(bytes) + sizeof result, std::reverse_iterator<unsigned char*>(reinterpret_cast<unsigned char*>(&result + 1)) ); return result; } 

On x86_64 it generates one movbe instruction - cannot get more efficient than that:

The MOVBE instruction is provided for swapping the bytes on a read from memory or on a write to memory; thus providing support for converting little-endian values to big-endian format and vice versa.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.