big endian vs little endian使用指针的疑惑

时间:2017-10-17 04:01:50

标签: c

请考虑以下代码:

uint16_t array[]={0xF924,0X120C,0X0733};
uint16_t *ptr=(uint16_t *)((array[0]&0xFF00)|(array[1]&0xFF));

考虑第一种情况,其中体系结构是大端,第二种情况是体系结构是小端。指针ptr在执行上述代码后将指向的地址是什么以及它将如何不同?

使用小端的答案answer using big endian有人可以解释为什么*ptr指向地址,如图所示。我的假设是它应该指向F90C而不是图中所示的地址

2 个答案:

答案 0 :(得分:4)

您的代码中没有任何内容取决于系统的字节顺序。

这部分

(array[0]&0xFF00)|(array[1]&0xFF)
无论字节顺序如何,

总是会给出相同的结果(此处为0xF90C)。

Endianess仅影响存储在内存中的字节顺序,但是一旦您以正确类型的整数访问数据,您就会在小端和大端系统上获得相同的值。

BTW - 你的代码有可疑的演员。您正在向uint16_t(即指针)投射uint16_t*。在大多数系统上,我都希望有一个警告,例如"从不同大小的整数转换为指针#34;。

答案 1 :(得分:2)

简短回答:同样,结束不影响表达。

说明:
在bigendian顺序中,多字节值中最具代表性的字节存储在最低地址
在小端序中,最有名的字节存储在最高地址。

假设你的代码示例代码是在bigendian环境中编译的,那么你的数组的内存将包含这样的字节(按字节顺序,按升序地址顺序,十六进制表示):

  • 0xF9
  • 的0x42
  • 0×12
  • 0x0C
  • 0x07的
  • 0x33

在小端环境中也会如此:

  • 的0x42
  • 0xF9
  • 0x0C
  • 0×12
  • 0x33
  • 0x07的

对数组成员的访问以及操作将因此在大端环境中产生:

(0xF924 & (0xFF00))|(0x120C&0xFF))
           (0xF900)|(0x0C)
                0xF90C

然而,这个表达式(它本身访问uint16_t成员而不是字节)将是
在小端环境中产生完全相同的

如果从uint16_t(来自任何索引)的数组中读取uint16_t,您将始终获得存储在该索引处的uint16_t。 Bigendian和little endian影响存储最多/最不重要字节的位置。但相应的编译器"知道"并将生成相应的代码。这通常(即在任何16位或更宽的平台上)意味着使用适当的汇编指令(馈送低位字节地址)。数据总线和其他数据访问机制确保16位在存储时被读取 即只有在8位平台上,生成的代码实际上才会知道两个字节,它们会被分开访问并暴露它们的字节地址。

你的表达方式(具有相同的价值,无论哪个字节顺序)实际上是一个有意义的地址,这是一个非常重要的问题。答案是"不要尝试,有龙",即未定义的行为。指针算术只适用于勇敢者。 ; - )

您可能打算编写使endianess可见的代码。这是可能的,但非常难看。我会尝试使用16位三位数组和8位6位数组的并集。但这将依赖于另一个未定义的行为(读取与最后写入的联合成员不同的联合成员)。