分类: C/C++
2016-11-29 11:31:57
原文地址:大小端格式说明与判断方法 作者:zhenhuaqin
1.概述:
1)大端格式:
在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
2)小端格式:
与大端存储格式相反,在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。如图2.2所示:
请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1
int checkCPU( )
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return(c.b ==1);
}
}
2.剖析:
嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 |
0x4000 |
0x4001 |
存放内容 |
0x34 |
0x12 |
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 |
0x4000 |
0x4001 |
存放内容 |
0x12 |
0x34 |
32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 |
0x4000 |
0x4001 |
0x4002 |
0x4003 |
存放内容 |
0x78 |
0x56 |
0x34 |
0x12 |
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 |
0x4000 |
0x4001 |
0x4002 |
0x4003 |
存放内容 |
0x12 |
0x34 |
0x56 |
0x78 |
联合体union的存放顺序是所有成员都从低地址开始存放。
内存地址 |
0x4000 |
0x4001 |
0x4002 |
0x4003 |
c.a |
1 |
0 |
0 |
0 |
小端c.b |
1 |
0 |
0 |
0 |
大端c.b |
0 |
0 |
0 |
1 |
3.判断大小端的方法解答:
1) 显然,解答这个问题的方法只能是将一个字节(CHAR/BYTE 类型)的数据和一个整型数据存放于同样的内存开始地址,通过读取整型数据,分析CHAR/BYTE 数据在整型数据的高位还是低位来判断CPU 工作于Little endian 还是Big endian 模式。得出如下的答案:
typedef unsigned char BYTE;
int main(int argc, char* argv[])
{
unsigned int num,*p;
p = #
num = 0;
*(BYTE *)p = 0xff;
if(num == 0xff)
{
printf("The endian of cpu is little\n");
}
else //num == 0xff000000
{
printf("The endian of cpu is big\n");
}
return 0;
}
2)我们可以将一个CHAR/BYTE 数据和一个整型数据同时作为一个union 的成员,得出如下答案:
int checkCPU()
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return (c.b == 1);
}
}
3)//检测系统字节顺序,即大小端模式
//编译方式gcc -o 目标可执行文件 源代码文件.c
#include
#include
#include
int main()
{
union
{
short inum;
char c[sizeof(short)];
}un;
struct utsname uts;
un.inum=0x0102;
if(uname(&uts)<0)
{
printf("Could not get host information.\n");
return -1;
}
printf("%s-%s-%s:\n",uts.machine,uts.sysname,uts.release);
if(sizeof(short)!=2)
{
printf("sizeof(short)=%d\n",sizeof(short));
return 0;
}
if(un.c[0]==1 && un.c[1]==2)
printf("big_endian.\n");
else if(un.c[0]==2 && un.c[1]==1)
printf("little_endian.\n");
else
printf("unknown.\n");
return 0;
}