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
C/C++ Source Code Visualization
C++ Access Derived Class Member from Base Class Pointer
Is Destructor Called If Sigint or Sigstp Issued
Cmake Externalproject_Add() and Findpackage()
How Will I Know Whether Inline Function Is Actually Replaced at the Place Where It Is Called or Not
Calculating the Amount of Combinations
Doing a Static_Assert That a Template Type Is Another Template
How to Replace All Instances of a String with Another String
Compile Time Triggered Range Check for Std::Vector
Polymorphic_Allocator: When and Why Should I Use It
What Does the Fpermissive Flag Do
Can Openssl on Windows Use the System Certificate Store
C++ Multiple Inheritance Function Call Ambiguity
Dynamically Allocated Memory After Program Termination