C++ Int to Byte Array

Converting an int into a 4 byte char array (C)

The portable way to do this (ensuring that you get 0x00 0x00 0x00 0xaf everywhere) is to use shifts:

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

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

The methods using unions and memcpy() will get a different result on different machines.


The issue you are having is with the printing rather than the conversion. I presume you are using char rather than unsigned char, and you are using a line like this to print it:

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

When any types narrower than int are passed to printf, they are promoted to int (or unsigned int, if int cannot hold all the values of the original type). If char is signed on your platform, then 0xff likely does not fit into the range of that type, and it is being set to -1 instead (which has the representation 0xff on a 2s-complement machine).

-1 is promoted to an int, and has the representation 0xffffffff as an int on your machine, and that is what you see.

Your solution is to either actually use unsigned char, or else cast to unsigned char in the printf statement:

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

Convert Bytes to Int / uint in C

Yes there is. Assume your bytes are in:

uint8_t bytes[N] = { /* whatever */ };

We know that, a 16 bit integer is just two 8 bit integers concatenated, i.e. one has a multiple of 256 or alternatively is shifted by 8:

uint16_t sixteen[N/2];

for (i = 0; i < N; i += 2)
sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8;
// assuming you have read your bytes little-endian

Similarly for 32 bits:

uint32_t thirty_two[N/4];

for (i = 0; i < N; i += 4)
thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8
| (uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24;
// same assumption

If the bytes are read big-endian, of course you reverse the order:

bytes[i+1] | (uint16_t)bytes[i] << 8

and

bytes[i+3] | (uint32_t)bytes[i+2] << 8
| (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24

Note that there's a difference between the endian-ness in the stored integer and the endian-ness of the running architecture. The endian-ness referred to in this answer is of the stored integer, i.e., the contents of bytes. The solutions are independent of the endian-ness of the running architecture since endian-ness is taken care of when shifting.

C++ int to byte array

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;
}

How to convert int to byte in c?

byte is a java signed integer type with a range of -128 to 127.
The corresponding type in C is int8_t defined in <stdint.h> for architectures with 8-bit bytes. It is an alias for signed char.

You can write:

#include <stdint.h>

void f() {
int num = 167;
int8_t b = num; // or signed char b = num;
...

If your compiler emits a warning about the implicit conversion to a smaller type, you can add an explicit cast:

    int8_t b = (int8_t)num;  // or signed char b = (signed char)num;

Note however that it is much more common to think of 8-bit bytes as unsigned quantities in the range 0 to 255, for which one would use type uint8_t or unsigned char. The reason java byte is a signed type might be that there is no unsigned type in this language, but it is quite confusing for non-native readers.

byte can also be defined as a typedef:

typedef unsigned char byte;  // 0-255;

or

typedef signed char byte;    // -128-127;

Do not use type char because it is implementation defined whether this type is signed or unsigned by default. Reserve type char for the characters in C strings, although many functions actually consider these to be unsigned: strcmp(), functions from <ctype.h>...

Convert an int into a 4 byte char array in C

It's almost certainly the case that "Dynamic C" is an implementation with an int of 16 bits, which is perfectly "legal" for C. If the int is 16 bits, any shift over 16 bits is modulo-16, so the second two shifts duplicate the first two.

Mask or not mask when converting int to byte array?

uint8 and uint32 are not standard types in C. I assume they represent 8-bit and 32-bit unsigned integral types, respectively (such as supported by Microsoft compilers as a vendor-specific extension).

Anyways ....

The masking is more general - it ensures the result is between 0 and 0xFF regardless of the actual type of elements someByteArray or of someInt.

In this particular case, it makes no difference, since the conversion of uint32 to uint8 is guaranteed to use modulo arithmetic (modulo 0xFF + 0x01 which is equal to 0x100 or 256 in decimal). However, if your code is changed to use variables or arrays of different types, the masking is necessary to ensure the result is between 0 and 255 (inclusive).

With some compilers the masking stops compiler warnings (it effectively tells the compiler that the expression produces a value between 0 and 0xFF, which can be stored in a 8 bit unsigned). However, some other compilers complain about the act of converting a larger type to an 8 bit type. Because of that, you will sometimes see a third variant, which truly demonstrates a "belts and suspenders" mindset.

uint8 someByteArray[4];
uint32 someInt;

someByteArray[0] = (uint8)((someInt >> 24) & 0xFF);
someByteArray[1] = (uint8)(someInt >> 16) & 0xFF);
someByteArray[2] = (uint8)((someInt >> 8) & 0xFF);
someByteArray[3] = (uint8)(someInt & 0xFF);

C++ | Convert int to byte[4] and vice versa

Your intToByte function is allocating a byte[4] within the scope of its body and then returning a pointer to it.

Consequently, the value is trashed as soon as your function returns and all the caller receives is a pointer to a now-invalid location - values are destroyed when they go out of scope and pointers do not extend that lifetime.

Either use a standard container object such as std::array or std::vector which your function should return to the caller or alternatively, have intToByte accept a byte[4]/byte* as an argument and fill it in.

For completeness... you could also have the function create the byte array using new, but then you'd have to remember to delete[] it, which, whilst seemingly an easy thing to do in this case, is generally bad practice when you have no good reason to make a dynamic allocation.

Additionally, the statement x & y >> z will first perform y >> z and then bitwise-AND the result with x, which is of course not what you want.



Related Topics



Leave a reply



Submit