I have unsigned char * data
like below:
unsigned char * data = ...;
data[0]=0x24;
data[1]=0x8A;
data[2]=0x07;
data[3]=0x75;
I want to convert it to uint16_t
with below code:
uint16_t *res= (uint16_t*)(data);
The output will be:
res[0]= 0x8A24; res[1]=0x7507
But I want res become like this:
res[0]=0x248A; res[1]=0x0775;
How can I change my code?
If you were to use operating system's header, you have the ntohs
and htons
function that can swap the bytes.
Else, it's trivial to add:
template <T> T swap_endianness(T in) {
unsigned char array[sizeof(in)] = {};
std::memcpy(array, &in, sizeof(in));
// Byte swap now
for (size_t i = 0; i < sizeof(in)/2; i++)
std::swap(array[i], array[sizeof(in) - i - 1]);
std::memcpy(&in, array, sizeof(in));
return in;
}
Usage is:
uint16_t *res= (uint16_t*)(data); // This is undefined behavior. Use memcpy instead.
res[0] = swap_endianness(res[0]); // and so on
This only works for Plain Old Data type, such as uint64
, uint32
, uint16
, int64
, int32
, int16
, float
, double
.
As @KamilCuk pointed out, the like (uint16_t *)(data)
might lead to issues if data
happens not to be aligned at 16-bit boundary and will likely cause a memory access error when you'll dereference it on platfrom like ARM. The correct solution is to use memcpy
like this:
uint16_t res[2];
std::memcpy(res, data, sizeof(res));
res[0] = swap_endianness(res[0]);
res[1] = swap_endianness(res[1]);
But I want res become like this:
How can I change my code?
It's just:
res[0] = data[0] << 8 | data[1];
res[1] = data[2] << 8 | data[3];
I want to convert it to uint16_t with below code:
uint16_t *res= (uint16_t*)(data);
The output will be:
Such code will be invalid and dereferencing res
results in undefined behavior. This is a strict alias violation and data
may not be aligned to alignof(uint16_t)
. If the compiler happens to generate code that doesn't result in a hard fault because of unaligned access, the result depends on the endianess of the target machine. But anyway, this is just undefined behavior.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.