字节顺序测试:为啥以下代码有效?
Posted
技术标签:
【中文标题】字节顺序测试:为啥以下代码有效?【英文标题】:Testing for Endianness: Why does the following code work?字节顺序测试:为什么以下代码有效? 【发布时间】:2011-09-27 17:15:35 【问题描述】:虽然我确实了解字节顺序,但我对以下代码的工作方式有点不清楚。我想这个问题不是关于字节序,而是关于 char * 指针和 int 如何工作,即类型转换。另外,如果变量word
不是short
而只是int
,会有什么不同吗?谢谢!
#define BIG_ENDIAN 0
#define LITTLE_ENDIAN 1
int byteOrder()
short int word = 0x0001;
char * byte = (char *) &word;
return (byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
【问题讨论】:
在运行时测试字节序是没有意义的——你已经知道编译时的字节序了。 三元运算符没有意义,return byte[0];
就足够了。
@Ben:上面的比较干净;它更明确,并且优雅地跟踪 #define
s 值的变化。
@paul:不是便携式的。
@jdv:你当然可以——你可以使用编译器预定义的宏(例如_LITTLE_ENDIAN_
),或者因为你,程序员,已经知道目标字节序,你可以定义自己的宏。不存在“可移植性”问题。
【参考方案1】:
这是一个可爱的小程序。您有一个单词被设置为十六进制文字 1。如果您有小端,当您将指针转换为 char 指针时,最低有效字节(在本例中为 0x01)将位于字节 [0]。因此,如果 0x01 位于偏移量 0,那么您知道它是小端序,否则如果 0x00 位于偏移量 0,则您知道最低有效字节存储在较高的内存位置(偏移量 1)。
注意:指针总是指向字/数据结构等的最低内存地址...
【讨论】:
【参考方案2】:一个短整数由两个字节组成,在本例中为0x00
和0x01
。在小端系统上,小字节在前,所以在内存中它显示为0x01
,然后是0x00
。大端系统自然是颠倒的。这是小端系统上短整数的指针的样子:
----------------------- -----------------------
| 0x01 | 0x00 | | | |
----------------------- -----------------------
&word &word+1
另一方面,字符指针总是按顺序递增。因此,通过获取整数的第一个字节的地址并将其转换为char *
指针,您可以按内存顺序递增整数的每个字节。这是对应的图表:
------------ ------------ ------------ ------------
| 0x01 | | 0x00 | | | | |
------------ ------------ ------------ ------------
&byte &byte+1 &byte+2 &byte+3
【讨论】:
这是类型双关语规则的一个例外。通过char *
指针访问任何数据类型都是有效的。
啊!当然。感谢@Oli 的更正。我删除了该部分。
@Oli 你有参考吗?
@Maxpm:从这个开始:cellperformance.beyond3d.com/articles/2006/06/…;我会在一分钟内拿出准确的 C 标准报价...
@Maxpm: C99, 6.5/7: “一个对象的存储值只能由具有以下类型之一的左值表达式访问:......字符类型。”【参考方案3】:
(char *)&word
指向word
的第一个(最低地址)char
(字节)。如果你的系统是 little-endian,这将对应于0x01
;如果是大端,则对应0x00
。
是的,无论word
是short
、int
还是long
(只要它们的大小比char
大),这个测试都应该有效。
【讨论】:
【参考方案4】:它告诉你short
的字节顺序。至少在某些机器上,short
正好是两个字节。它不一定告诉您int
或long
的字节顺序,当然,当整数类型大于两个字节时,选择不是二进制的。
真正的问题是你为什么想知道。编写代码几乎总是更简单、更健壮,这样它就无关紧要了。 (也有例外,但它们几乎总是涉及非常低级的代码,无论如何只能在一个特定的硬件上运行。如果你对硬件足够了解,可以编写这种代码,你就会知道字节序。)
【讨论】:
【参考方案5】:在考虑 big-endian 与 little-endian 时,我用来记住字节顺序的技巧是“名称应该相反”:
当您手写数字时,自然的做法是从左到右书写,从最高有效数字开始,以最低有效数字结束。在您的示例中,您首先写入最高有效字节(即 0),然后写入最低有效字节(即 1)。这就是大端的工作方式。当它将数据写入内存(增加字节地址)时,它以最不重要的字节结束 - “小”字节。所以,big-endian 实际上以小字节结束。
对于 little-endian 也是如此:它实际上以最重要的字节结束,即“大”字节。
您的源代码检查第一个字节(即 byte[0])是否是最重要的字节 (0),在这种情况下,它是“big-startian”或 little endian 字节顺序。
【讨论】:
以上是关于字节顺序测试:为啥以下代码有效?的主要内容,如果未能解决你的问题,请参考以下文章