请考虑以下代码:
uint16_t array[]={0xF924,0X120C,0X0733};
uint16_t *ptr=(uint16_t *)((array[0]&0xFF00)|(array[1]&0xFF));
考虑第一种情况,其中体系结构是大端,第二种情况是体系结构是小端。指针ptr
在执行上述代码后将指向的地址是什么以及它将如何不同?
答案 0 :(得分:4)
您的代码中没有任何内容取决于系统的字节顺序。
这部分
(array[0]&0xFF00)|(array[1]&0xFF)
无论字节顺序如何,总是会给出相同的结果(此处为0xF90C)。
Endianess仅影响存储在内存中的字节顺序,但是一旦您以正确类型的整数访问数据,您就会在小端和大端系统上获得相同的值。
BTW - 你的代码有可疑的演员。您正在向uint16_t
(即指针)投射uint16_t*
。在大多数系统上,我都希望有一个警告,例如"从不同大小的整数转换为指针#34;。
答案 1 :(得分:2)
简短回答:同样,结束不影响表达。
说明:
在bigendian顺序中,多字节值中最具代表性的字节存储在最低地址
在小端序中,最有名的字节存储在最高地址。
假设你的代码示例代码是在bigendian环境中编译的,那么你的数组的内存将包含这样的字节(按字节顺序,按升序地址顺序,十六进制表示):
在小端环境中也会如此:
对数组成员的访问以及操作将因此在大端环境中产生:
(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位数组的并集。但这将依赖于另一个未定义的行为(读取与最后写入的联合成员不同的联合成员)。