繁体   English   中英

通过memcpy将unsigned char数组转换为unsigned int返回unsigned char数组是相反的

[英]unsigned char array to unsigned int back to unsigned char array via memcpy is reversed

这不是跨平台代码......一切都在同一平台上执行(即endianess是相同的..小端)。

我有这个代码:


    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;

我希望buff的输出是“test”(由于缺少'/ 0'而带有垃圾尾随字符),而输出是“tset”。 显然改变我正在移动的字符顺序(3,2,1,0而不是0,1,2,3)解决了问题,但我不明白这个问题。 memcpy不是按照我的预期行事吗?

谢谢。

这是因为你的CPU是小端的 在内存中,数组存储为:

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

这通过增加 右侧的字节地址来表示。 但是,整数存储在内存中,左侧的最低有效字节:

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

这恰好代表整数0x74657374。 使用memcpy()将其复制到buff反转原始array的字节。

你是在一个小端平台上运行它。

在little-endian平台上,32位int存储在内存中,最低内存地址中的最低有效字节。 因此,位0-7存储在地址P,位8-15存储在地址P + 1中,位16-23存储在地址P + 2中,位24-31存储在地址P + 3中。

在您的示例中:位0-7 ='t',位8-15 ='s',位16-23 ='e',位24-31 ='t'

这就是字节写入内存的顺序:“tset”

如果您将内存作为单独的字节(无符号字符)进行寻址,则将按照它们写入内存的顺序读取它们。

在little-endian平台上,输出应该是tset 原始序列是从较低地址到较高地址的test 然后你把它放入一个unsigned int ,第一个't'进入最高有效字节,最后't'进入最低有效字节。 在小端机器上,最低有效字节存储在较低地址。 这是如何将它复制到最终的buf 这是它的输出方式:从最后的't'到第一个't',即tset

在大端机器上你不会观察到逆转。

如何在你的buff添加'\\0'

您已经为平台字节顺序编写了一个测试,它已经得出结论: little endian

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM