Unsigned char array in unsigned int back to unsigned char array via memcpy is canceled

This is not cross-platform code ... everything runs on the same platform (i.e. endianess is the same .. small 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 expect the result of buff to be "test" (with the garbage return symbol due to the lack of "/ 0"), but instead, the output will be "tset". Obviously changing the order of the characters that I shift (3, 2, 1, 0 instead of 0, 1, 2, 3) fixes the problem, but I don't understand the problem. Is memcpy not what I expect?

Thanks.

+4
source share
5 answers

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

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

This is displayed with increasing byte addresses on the right. However, an integer is stored in memory with the least significant bytes on the left:

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

This means that this is an integer 0x74657374. Using memcpy() to copy to buff overrides bytes from the original array .

+9
source

You run it on the little-endian platform.

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

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

So, the order in which bytes are written to memory: "tset"

If you address memory, and then as separate bytes (unsigned chars), you will read them in the order in which they are written into memory.

+2
source

On the little-endian platform, the output should be tset . The initial sequence was test from lower addresses to higher addresses. Then you put it in an unsigned int with the first 't' in the most significant byte, and the last 't' goes into the least significant byte. On a machine with a small limb, the least significant byte is stored at the bottom address. This is how it will be copied to the final buf . This is how it will be displayed: from the last 't' to the first 't', i.e. tset .

You won't notice a U-turn on a big car.

0
source

How to add '\0' to your buff ?

0
source

You wrote a test for byte order in the platform, and he concluded: little endian.

0
source

All Articles