C语言中的字节序和指针类型转换

4

我在我的机器上编写了一个C程序,其中以下部分是代码:

uint32_t test = 0x01020304;
uint8_t array[4];

memcpy(array, &test, 4);

printf("%02x %02x %02x %02x\n",array[0], array[1], array[2], array[3]);

它打印出 04030201,但我期望得到的是 01020304

我需要得出结论:我所使用的机器具有小端字节序架构吗?


2
是的,小端序在许多最近的CPU(Intel)中被使用。 - Pierre Emmanuel Lallemant
1
顺便说一下,memcpy参数的转换是不必要的。 - Peter - Reinstate Monica
2
@Raoul722 - 当你看到那个警告时,你的代码是 memcpy(array, test, 4); 还是 memcpy(array, &test, 4);(注意第二个上的 &)? 第二个例子是正确的,不应该给你一个警告。 - Andrew Henle
2
编译器不应该警告(gcc 4.9.3没有)。也许您无意中删除了转换中的“&”符号? - Peter - Reinstate Monica
显示剩余2条评论
2个回答

4
正如Mohit所说的,是的:输出显示最低有效位在内存中的较低地址上,或者说“小端在前”;或者说“Little Endian”。
这可能会有点令人困惑,特别是对于从左到右书写和阅读的西方人来说。我只能猜想那些阅读和书写希伯来语或阿拉伯语的人感到不那么困惑。
其中一个后果是,位移运算符的工作方向与它们所表明的方向相反。
关于任何字节顺序的优点和缺点已经进行了很多争论;最终并不重要,当然C语言的一个巨大成就就是足够抽象地摆脱具体的架构,以平滑差异并使程序可移植(但不防止访问位和字节)。
在小端模式下,令人难以理解的是,字节中的位仍然按升序排列(我们写的方式),从右到左,而字节按升序排列(如果我们将更高的地址写在左侧),从左到右。
另外,因特网字节顺序是大端模式,因此使用htonl()和相关函数非常重要。(请不要重新实现这些函数。)
小端字节顺序的一个好处是,无论在内存位置上假定什么数据类型,小值始终相同;如果您将32位int写入值为23的地址x,并稍后以char读取它,则为23;在大端模式机器上,它将为0。

位移运算符不会根据字节顺序而产生不同的结果。例如,a << n被定义为将a乘以2的n次方所得到的相同值。有些情况下,位移操作会导致未定义/未指定的行为,但这与字节顺序无关。还有一些中间端和混合端的机器存在。 - Peter
@Peter 没错。这就是为什么在小端架构中 << 将字节向右移位,如果您按传统方式将内存内容写在左侧的较低地址处。 - Peter - Reinstate Monica

1

我需要得出结论,我所使用的机器是小端架构吗?

是的。

请考虑以与字节序无关的方式复制和打印数据:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>

int main ()
{
  uint32_t test = 0x01020304;
  uint8_t array[4];

  for(size_t i=0; i<sizeof(uint32_t); i++)
  {
    size_t shift = 8 * (sizeof(uint32_t) - 1 - i);
    array[i] = (test >> shift) & 0xFF;
    printf("%.2" PRIx8 " ", array[i]);
  }

  return 0; 
}

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