Amogh
Amogh

Reputation: 4573

Convert Integer to 4 byte ungisned char vector (in Big endian byte order)

Suppose, I wanted to write decimal 31 in a binary file (which is already loaded into vector) in 4 bytes so I have to write as 00 00 00 1f, but I don't know how to convert decimal number in hex string (of 4 bytes)

So, expected hex in vector of unsigned char is:

0x00 0x00 0x00 0x1f // int value of this is 31

To do this I tried following:

std::stringstream stream;
stream << std::setfill('0') << std::setw(sizeof(int) * 2) << std::hex << 31;
cout << stream.str();

Output:

0000001f

Above line of code gives output in string format but I want it into vector of unsigned char in format of '0x', so my output vector should have elements after conversion as 0x00 0x00 0x00 0x1F.

Upvotes: 1

Views: 1039

Answers (2)

Some programmer dude
Some programmer dude

Reputation: 409166

Without bothering with endianness you could copy the int value into a character buffer of the appropriate size. This buffer could be the vector itself.

Perhaps something like this:

std::vector<uint8_t> int_to_vector(unsigned value)
{
    // Create a vector of unsigned characters (bytes on a byte-oriented platform)
    // The size will be set to the same size as the value type
    std::vector<uint8_t> buffer(sizeof value);

    // Do a byte-wise copy of the value into the vector data
    std::memcpy(buffer.data(), &value, sizeof value);

    return buffer;
}

The order of bytes in the vector will always in the host native order. If a specific order is mandated then each byte of the multi-byte value needs to be copied into a specific element of the array using bitwise operations (std::memcpy can't be used).

Also note that this function will break strict aliasing if uint8_t isn't an alias of unsigned char. And that uint8_t is an optional type, there are platforms which doesn't have 8-bit entities (though they are not common).


For an endianness-specific variant, where each value of a byte is extracted one by one and added to the vector, perhaps something like this:

std::vector<uint8_t> int_to_be_vector(unsigned value)
{
    // Create a vector of unsigned characters (bytes on a byte-oriented platform)
    // The size will be set to the same size as the value type
    std::vector<uint8_t> buffer(sizeof value);

    // For each byte in the multi-byte value, copy it to the "correct" place in the vector
    for (size_t i = buffer.size(); i > 0; --i)
    {
        // The cast truncates the value, dropping all but the lowest eight bits
        buffer[i - 1] = static_cast<uint8_t>(value);
        value >>= 8;
    }

    return buffer;
}

Example of it working

Upvotes: 4

JonatanE
JonatanE

Reputation: 941

You could use a loop to extract one byte at a time of the original number and store that in a vector.

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <vector>

using u8 = std::uint8_t;
using u32 = std::uint32_t;

std::vector<u8> GetBytes(const u32 number) {
    const u32 mask{0xFF};
    u32 remaining{number};

    std::vector<u8> result{};
    while (remaining != 0u) {
        const u32 bits{remaining & mask};
        const u8 res{static_cast<u8>(bits)};
        result.push_back(res);
        remaining >>= 8u;
    }
    std::reverse(std::begin(result), std::end(result));
    return result;
}

int main() {
    const u32 myNumber{0xABC123};
    const auto bytes{GetBytes(myNumber)};
    std::cout << std::hex << std::showbase;
    for (const auto b : bytes) {
        std::cout << static_cast<u32>(b) << ' ';
    }
    std::cout << std::endl;
    return 0;
}

The output of this program is:

0xab 0xc1 0x23

Upvotes: 1

Related Questions