测试主机序号的例子(大端序、小端序、big_endian、little_endian)

1 由来:

大端序小端序原本是 《格列佛游记》中小人国一场争议而得来的,在小人国中,为了吃鸡蛋分为两派人,一派人建议从大头吃(称为big_endian),一拍人建议从小头吃(称为little_endian)。两派人各持己见,为此发起内战,还弄死了几个皇帝。呵呵,后来一个学者在他的论文中引用起来用来描述主机中多字节数据在 内存存储的顺序问题,命名为big_endian 和little_endian ,翻译中中文为大端序和小端序。 大端小端由此而来。 注意,只有涉及到多字节存储时,才会有大小端的概念。

 

2 描述:

在格列佛游记中,big_endian派的人建议从鸡蛋的大头吃,little_endian派的人建议从鸡蛋的小头吃。

对应计算机中的是多字节在内存中存储时(存储的默认顺序是从 内存的低地址向内存的高地址存储,如先从内存ox0001 处存储,接着向ox0002处储值。。。),

先把 “多字节”中的大头即高位 存储称之为大端序(big_endian),先把“多字节”中的小头即 低字节进行存储则称之为小端序(litten_endian) 。与吃鸡蛋的大小头类似。

比如一个int型变量是ox 12 34 56 78 ,

当主机字节序为  大端序(big_endian)时,地址和内容对应关系如下图:

内存地址:OX0001       0X0002    OX0003         0X0004 

内存内容: 0X12             OX34           OX56            OX78

  

当主机字节序为  小端序(litten_endian)时,地址和内容对应关系如下图:

内存地址:OX0001       0X0002    OX0003         0X0004 

内存内容: 0X78            OX56           OX34            OX12

 

3 分类:

不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
处理器         操作系统     字节排序
Alpha            全部     Little endian
HP-PA             NT      Little endian
HP-PA            UNIX     Big endian
Intelx86         全部     Little endian <-----x86系统是小端字节序系统
Motorola680x()   全部     Big endian
MIPS              NT      Little endian
MIPS             UNIX     Big endian
PowerPC           NT      Little endian
PowerPC          非NT     Big endian   <-----PPC系统是大端字节序系统
RS/6000          UNIX     Big endian
SPARC            UNIX     Big endian
IXP1200 ARM核心 全部     Little endian

 4  测试

为了测试本地机器的主机字节序,给出两种方法。注:这是从网上找的,具体记不起来是哪位兄弟了。

/*******************
* 文件名:endian.c
******************/
#include 

/*********************************************************
* 使用类型的强制转换实现little-endian与big-endian的判断
*********************************************************
* 返回值:  1 表示是小端字节序。 0 表示不是小端字节序。
*********************************************************/
int is_little_endian_a(void)
{
	unsigned short flag = 0x4321;

	if(*(unsigned char*)&flag == 0x21)
		return 1;
    else
        return 0;
}

/*********************************************************************************
* 利用联合的特点来判断little-endian与big-endian
*********************************************************************************
* 返回值:
*          1   表示是小端字节序。
*          0   表示是大端字节序。
*          -1  表示不能使用这种方法确定字节序。比如有的机器的 short 长度不是 2 。
********************************************************************************/

int is_little_endian_b(void)
{
   union endian_un
   {
       short var;
       char bits[sizeof(short)];
   };

    union endian_un flag;
    flag.var=0x0102;

    //判断低位和高位的存储内容,确定是何种方式
    if (sizeof(short) == 2)
    {
        if(flag.bits[0] == 1 && flag.bits[1] == 2)
             return 0;
        else if (flag.bits[0] == 2 && flag.bits[1] == 1)
             return 1;
        else
            return -1;
     }

     return -1;
}

 
int main(void)
{
    int type = 0;
    type = is_little_endian_a();

    if (1 == type)
        printf("judged by first method, little-endian\n");
    else if (0 == type)
        printf("judged by first method, big-endian\n");

    type = is_little_endian_b();

    if (1 == type)
        printf("judged by second method, little-endian\n");
    else if (0 == type)
        printf("judged by second method, big-endian\n");
    else
        printf("can't judge it\n");

    return 0;
}


其中a方法的思路找一个占用多字节的变量,然后取其变量的首字节内容,并通过&预算符判断,如果等于低字节的内容,则为小端序,否则为大端序。

其中b方法通过union来判断字节序,主要用到了UNION共用存储空间的特性。

 

 5  转换

本节主要讲述在网络通信当中主机字节序的转换问题。。

 

 

你可能感兴趣的:(C&C++)