通过memcpy将无符号字符数组转换为无符号整数,再将其转换回无符号字符数组是可逆的。

4

这不是跨平台代码... 所有操作都在同一个平台上执行(即字节序相同.. 小端)。

我有以下代码:


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

我期望 buff 的输出是 "test"(由于缺少 '/0',会有一个垃圾尾随字符),但实际输出是 "tset"。显然,改变我移位的字符顺序(3、2、1、0 而不是 0、1、2、3)可以解决问题,但我不明白问题出在哪里。memcpy 是否没有按照我的期望操作?谢谢。
5个回答

9

这是因为您的CPU是小端字节序。在内存中,该数组按以下方式存储:

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

这是用递增的字节地址表示向右侧。然而,整数在内存中以最不重要字节存储在左侧:

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

这代表整数0x74657374。使用memcpy()将其复制到buff中会颠倒原始array的字节顺序。


啊,我真是太蠢了。谢谢你的解释。 - bizack

2

您正在运行在小端平台上。

在小端平台上,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”

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


0
在小端平台上,输出应该是tset。原始序列是从低地址到高地址的test。然后将其放入一个unsigned int中,其中第一个“t”进入最高字节,最后一个“t”进入最低字节。在小端机器上,最不重要的字节存储在较低的地址处。这就是它将被复制到最终的buf的方式。这就是它将被输出的方式:从最后一个“t”到第一个“t”,即tset
在大端机器上,您将不会观察到反转。

0

你考虑过在你的buff末尾添加一个'\0'吗?


0
你已经编写了一个平台字节顺序的测试,并得出结论:小端

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接