我看到了一种了解平台端序的方法,就是这个程序,但我不理解它
#include <stdio.h>
int main(void)
{
int a = 1;
if( *( (char*)&a ) == 1) printf("Little Endiann");
else printf("Big Endiann");
system("PAUSE");
return 0;
}
这个测试做什么?
int
几乎总是大于一个字节,并且经常跟踪体系结构的字大小。例如,32位体系结构可能具有32位int。因此,给定典型的32位整数,4个字节的布局可能是:
00000000 00000000 00000000 00000001
或者先用最低有效字节:
00000001 00000000 00000000 00000000
char*是一个字节,所以如果我们将这个地址转换为char*,我们将获得上面的第一个字节,或者
00000000
或
00000001
因此,通过检查第一个字节,我们可以确定体系结构的字节序。
这只适用于sizeof(int) > 1
。举个例子,我们假设它是2,并且char
是8位。
基本上,对于little-endian,数字1作为一个16位整数看起来是这样的:
00000001 00000000
但对于big-endian,它是:
00000000 00000001
因此,首先代码设置a = 1
,然后这个:
*( (char*)&a ) == 1)
获取a
的地址,将其视为指向char
的指针,并取消对其的引用。因此:
如果
a
包含一个小的endian整数,您将得到00000001
部分,当作为char
插入时,它是1如果
a
包含一个大端数整数,那么您将得到00000000
。对== 1
的检查将失败,代码将假定平台是big-endian。
您可以使用int16_t
和int8_t
而不是int
和char
来改进此代码。或者更好的是,只需检查htons(1) != 1
。
- 您可以将整数视为4个字节的数组(在大多数平台上)。一个小端序整数将具有值
01 00 00 00
和一个大端序00 00 00 01
- 通过执行
&a
,您可以获得该数组的第一个元素的地址 - 表达式
(char*)&a
将其强制转换为单个字节的地址 - 最后
*( (char*)&a )
得到该地址所包含的值
- 取
a
的地址 - 将其投射到
char*
- 取消引用此
char*
,这将为您提供int
的第一个字节 - 检查它的值——如果它是
1
,那么它就是小端序。否则——大
假设sizeof(int) == 4
,则:
|........||........||........||........| <- 4bytes, 8 bits each for the int a
| byte#1 || byte#2 || byte#3 || byte#4 |
当执行步骤1、2和3时,*( (char*)&a )
将为您提供第一个字节| byte#1 |
。
然后,通过检查byte#1
的值,您可以了解它是big还是little endian。
程序只是将int
占用的空间重新解释为char
s的数组,并假设作为int的1
将存储为一系列字节,其中最低阶为值为1的字节,其余为0。
因此,如果最低阶字节首先出现,那么平台是小端序,否则是大端序。
这些假设可能不适用于现有的每个平台。
a = 00000000 00000000 00000000 00000001
^ ^
| |
&a if big endian &a if little endian
00000000 00000001
^ ^
| |
(char*)&a for BE (char*)&a for LE
*(char*)&a = 0 for BE *(char*)&a = 1 for LE
以下是它的分解方式:
a -- given the variable a
&a -- take its address; type of the expression is int *
(char *)&a -- cast the pointer expression from type int * to type char *
*((char *)&a) -- dereference the pointer expression
*((char *)&a) == 1 -- and compare it to 1
基本上,强制转换(char *)&a
将表达式&a
的类型从指向int
的指针转换为指向char
的指针;当我们将解引用运算符应用于结果时,它会给出存储在a
的第一个字节中的值。
*( (char*)&a )
在BigEndian中,int i=1(大小为4字节)的数据将在内存中排列为:-(从较低地址到较高地址)。
00000000 -->Address 0x100
00000000 -->Address 0x101
00000000 -->Address 0x102
00000001 -->Address 0x103
而LittleEndian是:-
00000001 -->Address 0x100
00000000 -->Address 0x101
00000000 -->Address 0x102
00000000 -->Address 0x103
分析以上铸件:-
还有&a= 0x100
,因此*((char*)0x100)
意味着考虑一次取一个字节(因为int加载了4个字节),因此0x100处的数据将被引用。
*( (char*)&a ) == 1 => (*0x100 ==1) that is 1==1 and so true,implying its little endian.