user3665224
user3665224

Reputation: 1357

memcpy of uint8_t to uint16_t

I have a code

#include <iostream>
#include <string.h>
using namespace std;

int main() {
    // your code goes here
    uint8_t x[4] = {55, 11, 0, 20};
    uint16_t y;
    memcpy(&y, &x[0], 2);
    std::cout<<y<<std::endl;
    return 0;
}

(hex of 55 - 37, hex of 11 - B) in which I expect y to contain "37B"(i.e., - 891 in decimal). But, Y actually contains "B37"(i.e., 2871 in decimal). How to maintain the order with memcpy without endian swap operation.

Upvotes: 0

Views: 7716

Answers (2)

dbush
dbush

Reputation: 223767

The reason you're getting B37 is because you're on a little-endian machine.

The call to memcpy is doing what you would expect. The value 0x37 is copied to the first byte of y, while 0x0B is copied to the second byte of y. And because you're on a little-endian architecture, the first byte of y is the least significant. So it contains the value 0xB37.

If you want x[0] to be the high byte and x[1] to be the low byte of y, you need to do it in a way that doesn't depend on endianness:

y = x[1];          // y = 0x0B
y |= x[0] << 8;    // y = 0x0B | 0x3700 = 0x370B

This will give y a value of 0x370B. However this is still not the 0x37B value you expect.

If that's what you want, you need to recognize that 0x37B has a value of 0x03 for the high byte and 0x7B for the low byte.

So you would either need to define x as follows:

// note the use of hex constants to make the values more clear
uint8_t x[4] = {0x7b, 0x3, 0x0, 0x14};   

Or you would need to perform some additional bit shifting to get the values you need:

y = x[1];          // y = 0x0B
y |= x[0] << 4;    // y = 0x0B | 0x370 = 0x37B

Upvotes: 1

user1084944
user1084944

Reputation:

memcpy copies memory. And it does maintain the order of the bytes of memory. You can't make memcpy do something else.

Your problem is that you don't want to copy memory; you want to do some particular arithmetic operation (e.g. concatenate two 8-bit values to get a 16-bit value).

Exactly how integer types are laid out in memory is unspecified behavior. On your CPU, your memcpy hack does not perform the arithmetic operation you want. Thus, to do what you want, have to do something other than (or in addition to) memcpy.

I advise doing the arithmetic operation with arithmetic operations: you'll get code you can be sure works on everything*, and your program will most likely perform similarly (or even better) than the hack anyways, especially with compiler optimizations turned on.

*: everything that has the relevant types, of course

Upvotes: 3

Related Questions