Given a char buffer c containing an int (little endian). How to read it as int32_t?
I wrote this code but it doesn't feel idiomatic cpp.
int32_t v;
char* p = (char*)&v;
for (int i=0; i < 4; i++) {
*(p+i) = *(c+i);
}
Given a char buffer c containing an int (little endian). How to read it as int32_t?
I wrote this code but it doesn't feel idiomatic cpp.
int32_t v;
char* p = (char*)&v;
for (int i=0; i < 4; i++) {
*(p+i) = *(c+i);
}
The only portable way to copy binary data from a char*
buffer to any other data type is with memcpy
(or an equivalent byte-copying merhod such as std::copy
or one of your own that mimics this behaviour).
memcpy(&my_number, my_buffer, sizeof(my_number));
Of course the buffer should contain correct bits for a given data type. If it originated from memory copying from the same data tyoe on the same machine, then endianness doesn't come into play. Otherwise you have to rearrange the bytes in the required order (either in place or in a temporary buffer), or swap the bytes in a platform-dependent manner in the in the integer itself (maybe with htonl and friends).
There is no magic idiomatic way to handle endianness — endianness is an I/O issue. Either use the htonl()
and ntohl()
functions (available on every system) or just decode them yourself (as you are doing). I recommend writing functions to do it (make your life easier, and verifiable).
If you want to solve your issue in a portable and safe manner, use memcpy
as n.m.'s answer explains. Otherwise, here's a more dangerous technique:
Note that this is UB. Only use the technique below if you are completely sure that the buffer contains the right amount of data and that the buffer and data are properly aligned.
If you are sure that the endianness of the system matches the one of the data stored in the char*
buffer, you can use reinterpret_cast
:
std::int32_t v = *reinterpret_cast<std::int32_t*>(p);
There's no Standard-compliant way of doing the above transformation. See this question for more details.
There is no standard function to discover the endianness of your system. However given such a function bool is_little_endian()
that returns true only on little endian systems you might do something like this:
std::uint32_t read_from_little_endian(char* buf)
{
std::uint32_t u;
if(is_little_endian())
std::copy(buf, buf + sizeof(u), (char*)&u);
else
std::reverse_copy(buf, buf + sizeof(u), (char*)&u);
return u;
}
The important point is always to cast your std::uint32_t*
to a char*
because only char*
can legally alias all other types.