C++ int to byte array
Asked Answered
G

11

45

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++?

Gameness answered 7/4, 2011 at 18:5 Comment(0)
M
33

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;
}
Mella answered 7/4, 2011 at 18:20 Comment(3)
The Java code generates a big endian representation; you generate a littel endian one. (I'd also just use the shift count as the loop control: int i = 32; while ( i != 0 ) { arrayOfByte[i] = paramInt >> i; i -= 8; }Ebenezer
@JamesKanze: wait... can you really use i to access arrayOfByte when it will have values of [32, 24, 16, 8]? I think you should do arrayOfByte[i/8].Emmettemmey
@TomášZato Yes; The index should be i/8.Ebenezer
A
84

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.

Afterthought answered 7/4, 2011 at 18:7 Comment(5)
Maybe. Not on an Intel box (or at least it won't give the same results).Ebenezer
I'm curious: why did you do two static_cast<>s instead of one reinterpret_cast<>?Bypath
To elaborate: There was lengthy discussion here a year or two ago about whether a reinterpret_cast was guaranteed to be equivalent to the pair of static_cast. If I recall correctly it was basically agreed that both should always work, but it was all very convoluted so I still avoid reinterpret_cast.Afterthought
The result of this method seems to depend on the endianness. Assume x=0x4142, run this process on a little endian machine, iterate the bytes array and print each byte, you'll get "BA". If you want to get "AB", you have to reverse the result by yourself.Pesach
Is it well defined to cast an int to a byte array? I thought accessing an object as if it were some other type is undefined behavior.Slumberous
M
33

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;
}
Mella answered 7/4, 2011 at 18:20 Comment(3)
The Java code generates a big endian representation; you generate a littel endian one. (I'd also just use the shift count as the loop control: int i = 32; while ( i != 0 ) { arrayOfByte[i] = paramInt >> i; i -= 8; }Ebenezer
@JamesKanze: wait... can you really use i to access arrayOfByte when it will have values of [32, 24, 16, 8]? I think you should do arrayOfByte[i/8].Emmettemmey
@TomášZato Yes; The index should be i/8.Ebenezer
E
23

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
Eft answered 7/4, 2011 at 18:9 Comment(0)
V
13

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.

Viole answered 14/2, 2013 at 11:32 Comment(3)
Reading from wrong union member is Undefined Behavior and misuse of unionImprinting
This is wrong. This is not what unions are for. This is not how unions work. Myth!Magnetograph
On some machines this is very clever, but sadly it's not standard and is dangerous. See this union reference. "The union is only as big as necessary to hold its largest data member. The other data members are allocated in the same bytes as part of that largest member. The details of that allocation are implementation-defined, and it's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union."Particle
D
10

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;
Deglutinate answered 11/4, 2019 at 1:26 Comment(0)
E
8
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;
}
Ebenezer answered 7/4, 2011 at 18:31 Comment(0)
D
6

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);
Deciare answered 20/4, 2017 at 9:38 Comment(0)
R
4

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;
}
Rounce answered 15/1, 2019 at 10:51 Comment(1)
should be the one and only answer as the most universal and magic-number-less solutionDisbursement
K
2

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().

Karinekariotta answered 7/6 at 11:34 Comment(0)
S
0
return ((byte[0]<<24)|(byte[1]<<16)|(byte[2]<<8)|(byte[3]));

:D

Stopped answered 7/4, 2011 at 18:8 Comment(4)
he asked exactly the opposite :)Eft
wow, I fail! Always feel like if I don't reply right away a million other people will. I was right, but I suppose I should make sure to get the question right hahahaStopped
yeah, me too try to answer as fast as possible, and sometimes write such a bullsh*ts ;)Eft
It's still useful.Peursem
H
0

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;
}
Heist answered 22/8, 2019 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.