Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unsigned char array to unsigned int back to unsigned char array via memcpy is reversed

Tags:

c++

c

This isn't cross-platform code... everything is being performed on the same platform (i.e. endianess is the same.. little endian).

I have this code:


    unsigned char array[4] = {'t', 'e', 's', 't'};
unsigned int out = ((array[0]<<24)|(array[1]<<16)|(array[2]<<8)|(array[3])); std::cout << out << std::endl;
unsigned char buff[4]; memcpy(buff, &out, sizeof(unsigned int));
std::cout << buff << std::endl;

I'd expect the output of buff to be "test" (with a garbage trailing character because of the lack of '/0') but instead the output is "tset." Obviously changing the order of characters that I'm shifting (3, 2, 1, 0 instead of 0, 1, 2, 3) fixes the problem, but I don't understand the problem. Is memcpy not acting the way I expect?

Thanks.

like image 392
bizack Avatar asked Dec 23 '22 08:12

bizack


2 Answers

This is because your CPU is little-endian. In memory, the array is stored as:

      +----+----+----+----+
array | 74 | 65 | 73 | 74 |
      +----+----+----+----+

This is represented with increasing byte addresses to the right. However, the integer is stored in memory with the least significant bytes at the left:

    +----+----+----+----+
out | 74 | 73 | 65 | 74 |
    +----+----+----+----+

This happens to represent the integer 0x74657374. Using memcpy() to copy that into buff reverses the bytes from your original array.

like image 93
Greg Hewgill Avatar answered Apr 09 '23 23:04

Greg Hewgill


You're running this on a little-endian platform.

On a little-endian platform, a 32-bit int is stored in memory with the least significant byte in the lowest memory address. So bits 0-7 are stored at address P, bits 8-15 in address P + 1, bits 16-23 in address P + 2 and bits 24-31 in address P + 3.

In your example: bits 0-7 = 't', bits 8-15 = 's', bits 16-23 = 'e', bits 24-31 = 't'

So that's the order that the bytes are written to memory: "tset"

If you address the memory then as separate bytes (unsigned chars), you'll read them in the order they are written to memory.

like image 20
Jesper Avatar answered Apr 10 '23 01:04

Jesper