justme_
justme_

Reputation: 665

C++ int to byte array

I have this method in my java code which returns byte array for given int:

private static byte[] intToBytes(int paramInt)
{
     byte[] arrayOfByte = new byte[4];
     ByteBuffer localByteBuffer = ByteBuffer.allocate(4);
     localByteBuffer.putInt(paramInt);
     for (int i = 0; i < 4; i++)
         arrayOfByte[(3 - i)] = localByteBuffer.array()[i];
     return arrayOfByte;
}

Can someone give me tip how can i convert that method to C++?

Upvotes: 46

Views: 184631

Answers (11)

Arc_Angle
Arc_Angle

Reputation: 65

Use C++20's std::bit_cast!

#include <bit>
#include <array>

using byte = unsigned char; // might want to use std::byte instead
constexpr std::size_t bytes_in_int = sizeof(int) / sizeof(byte);

auto int_to_bytes(int value)
{
    return std::bit_cast<std::array<byte, bytes_in_int>>(value);
}

This method copies the integer "as an array" to house its bytes.

As a bonus, it is constexpr and does not require any heap allocations (unlike a vector). Additionally, this compiles to only a single instruction:

int_to_bytes(int):
        movl    %edi, %eax
        ret

(tested on gcc and clang with -O3)

A tip: if you want to get the big/little endian representation, and use it for iteration, you can create an array this way and iterate over it in reverse using .rbegin() and .rend().

Upvotes: 3

canellas
canellas

Reputation: 697

I hope mine helps

template <typename t_int>
std::array<uint8_t, sizeof (t_int)> int2array(t_int p_value) {
    static const uint8_t _size_of (static_cast<uint8_t>(sizeof (t_int)));
    typedef std::array<uint8_t, _size_of> buffer;
    static const std::array<uint8_t, 8> _shifters = {8*0, 8*1, 8*2, 8*3, 8*4, 8*5, 8*6, 8*7};

    buffer _res;
    for (uint8_t _i=0; _i < _size_of; ++_i) {
        _res[_i] = static_cast<uint8_t>((p_value >> _shifters[_i]));
    }
    return _res;
}

Upvotes: 0

SportySpice
SportySpice

Reputation: 365

An int (or any other data type for that matter) is already stored as bytes in memory. So why not just copy the memory directly?

memcpy(arrayOfByte, &x, sizeof x);

A simple elegant one liner that will also work with any other data type.



If you need the bytes reversed you can use std::reverse

memcpy(arrayOfByte, &x, sizeof x);
std::reverse(arrayOfByte, arrayOfByte + sizeof x);

or better yet, just copy the bytes in reverse to begin with

BYTE* p = (BYTE*) &x;
std::reverse_copy(p, p + sizeof x, arrayOfByte);

If you don't want to make a copy of the data at all, and just have its byte representation

BYTE* bytes = (BYTE*) &x;

Upvotes: 11

NutCracker
NutCracker

Reputation: 12283

I know this question already has answers but I will give my solution to this problem. I am using template function and integer constraint on it.

Here is my solution:

#include <type_traits>
#include <vector>

template <typename T,
          typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
std::vector<uint8_t> splitValueToBytes(T const& value)
{
    std::vector<uint8_t> bytes;

    for (size_t i = 0; i < sizeof(value); i++)
    {
        uint8_t byte = value >> (i * 8);
        bytes.insert(bytes.begin(), byte);
    }

    return bytes;
}

Upvotes: 4

Sarath AK
Sarath AK

Reputation: 71

Int to byte and vice versa.

unsigned char bytes[4];
unsigned long n = 1024;

bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;

printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);


int num = 0;
for(int i = 0; i < 4; i++)
 {
 num <<= 8;
 num |= bytes[i];
 }


printf("number %d",num);

Upvotes: 6

NullData
NullData

Reputation: 414

Another useful way of doing it that I use is unions:

union byteint
{
    byte b[sizeof int];
    int i;
};
byteint bi;
bi.i = 1337;
for(int i = 0; i<4;i++)
    destination[i] = bi.b[i];

This will make it so that the byte array and the integer will "overlap"( share the same memory ). this can be done with all kinds of types, as long as the byte array is the same size as the type( else one of the fields will not be influenced by the other ). And having them as one object is also just convenient when you have to switch between integer manipulation and byte manipulation/copying.

Upvotes: 13

Donotalo
Donotalo

Reputation: 13035

Using std::vector<unsigned char>:

#include <vector>
using namespace std;

vector<unsigned char> intToBytes(int paramInt)
{
     vector<unsigned char> arrayOfByte(4);
     for (int i = 0; i < 4; i++)
         arrayOfByte[3 - i] = (paramInt >> (i * 8));
     return arrayOfByte;
}

Upvotes: 33

James Kanze
James Kanze

Reputation: 154047

std::vector<unsigned char> intToBytes(int value)
{
    std::vector<unsigned char> result;
    result.push_back(value >> 24);
    result.push_back(value >> 16);
    result.push_back(value >>  8);
    result.push_back(value      );
    return result;
}

Upvotes: 8

BlackBear
BlackBear

Reputation: 22989

You can get individual bytes with anding and shifting operations:

byte1 =  nint & 0x000000ff
byte2 = (nint & 0x0000ff00) >> 8
byte3 = (nint & 0x00ff0000) >> 16
byte4 = (nint & 0xff000000) >> 24

Upvotes: 24

jberg
jberg

Reputation: 4816

return ((byte[0]<<24)|(byte[1]<<16)|(byte[2]<<8)|(byte[3]));

:D

Upvotes: 0

James McNellis
James McNellis

Reputation: 355307

You don't need a whole function for this; a simple cast will suffice:

int x;
static_cast<char*>(static_cast<void*>(&x));

Any object in C++ can be reinterpreted as an array of bytes. If you want to actually make a copy of the bytes into a separate array, you can use std::copy:

int x;
char bytes[sizeof x];
std::copy(static_cast<const char*>(static_cast<const void*>(&x)),
          static_cast<const char*>(static_cast<const void*>(&x)) + sizeof x,
          bytes);

Neither of these methods takes byte ordering into account, but since you can reinterpret the int as an array of bytes, it is trivial to perform any necessary modifications yourself.

Upvotes: 85

Related Questions