little endian和big endian的概念解释,判定与用途

孤者浪人 提交于 2019-12-07 11:07:37

转贴地址:http://www.chinaunix.net/jh/23/823662.html

#######################

//声明: 1  本帖作者是:converse ,至此感谢!

              2  红色背景字体为本人添加内容!

              3  黄色背景为个人阅读重点!

#######################


little endian和big endian的概念解释,判定与用途

       little endian和big endian是表示计算机字节顺序的两种格式,所谓的字节顺序指的是长度跨越多个字节的数据的存放形式. 

        假设从地址0x00000000开始的一个字中保存有数据0x1234abcd,那么在两种不同的内存顺序的机器上从字节的角度去看的话分别表示为: 
       1)little endian:在内存中的存放顺序是0x00000000-0xcd,0x00000001-0xab,0x00000002-0x34,0x00000003-0x12 
       2)big  endian:在内存中的存放顺序是0x00000000-0x12,0x00000001-0x34,0x00000002-0xab,0x00000003-0xcd 
       需要特别说明的是,以上假设机器是每个内存单元以8位即一个字节为单位的. 

       简单的说,little endian把低字节存放在内存的低位;而big endian将低字节存放在内存的高位.  

                      字节                         little endian                           big endian                内存                       

     低         0x0000000                        cd                                         12                       12          高位        

      |            0x0000001                        ab                                         34                       34            |            

     ∨          0x0000002                        34                                         ab                        ab           ∨         

     高          0x0000003                        12                                         cd                        cd         低位        

       现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian. 

        
       以下是判断字节存储顺序的可移植的C语言代码: 
 /********************************************************************

	created:	2006-9-5

	filename: 	test.cpp

	author:		李创

	

	purpose:	可移植的用于判断存储格式是

                little endian还是big ednian的C代码

                取自<<C: A Reference Manual>>

*********************************************************************/



#include <stdio.h>



union

{

	long Long;

	char Char[sizeof(long)];

}u;



int main()

{	

	u.Long = 1;

	

	if (u.Char[0] == 1)	

	{

		printf("Little Endian!\n");

	}

	else if (u.Char[sizeof(long) - 1] == 1)

	{

		printf("Big Endian!\n");

	}

	else

	{

		printf("Unknown Addressing!\n");

	}



    printf("Now, Let's look at every byte in the memory!\n");

    for (int i = 0; i < sizeof(long); ++i)

    {

        printf("[%x] = %x\n", &u.Char, u.Char);

    }



	return 0;

}


 很多人认为掌握这个知识是不必要,其实不然.在网络编程中,TCP/IP统一采用big endian方式传送数据,也就是说,假设现在是在一个字节顺序是little endian的机器上传送数据,要求传送的数据是0XCEFABOBO,那么你就要以0XBOBOFACE的顺序在unsigned int中存放这个数据,只有这样才能保证存放的顺序满足TCP/IP的字节顺序要求.很多时候,需要自己编写应用层的协议,字节顺序的概念在这个时候就显得及其的重要了. 
       下面给出的是在big endian和little endian中相互转换的代码,C语言强大的位操作的能力在这里显示了出来: 

/********************************************************************

	created:	2006-9-5

	filename: 	get32put32.cpp

	author:		李创

	

	purpose:	在little endian和big ednian之间相互转化数据的演示代码



*********************************************************************/





#include <stdio.h>



const unsigned char SIZE_OF_UNSIGNEDINT  = sizeof(unsigned int);

const unsigned char SIZE_OF_UNSIGNEDCHAR = sizeof(unsigned char);



void put_32(unsigned char *cmd, unsigned int data)

{

    int i;

    for (i = SIZE_OF_UNSIGNEDINT - 1; i >= 0; --i)

    {

        cmd = data % 256;

        // 或者可以:

        //cmd = data & 0xFF;

        data = data >> 8;

    }

}



unsigned int get_32(unsigned char *cmd)

{

    unsigned int  ret;

    int i;



    for (ret = 0, i = SIZE_OF_UNSIGNEDINT - 1; i >= 0; --i)

    {

        ret  = ret << 8;

        ret |= cmd;        

    }

	

    return ret;

}



int main(void)

{

    unsigned char cmd[SIZE_OF_UNSIGNEDINT];

    unsigned int data, ret;

    unsigned char *p;

    int i;



    data = 0x12345678;

    printf("data = %x\n", data);

    // 以字节为单位打印出数据

    p = (unsigned char*)(&data);

    for (i = 0; i < SIZE_OF_UNSIGNEDINT; ++i)

    {

        printf("%x", *p++);

    }

    printf("\n");



    // 以相反的顺序存放到cmd之中

    put_32(cmd, data);

    for (i = 0; i < SIZE_OF_UNSIGNEDINT; ++i)

    {

        printf("cmd[%d] = %x\n", i, cmd);

    }



    // 再以相反的顺序保存数据到ret中

    // 保存之后的ret数值应该与data相同

    ret = get_32(cmd);

    printf("ret = %x\n", ret);

    p = (unsigned char*)(&ret);

    for (i = 0; i < SIZE_OF_UNSIGNEDINT; ++i)

    {

        printf("%x", *p++);

    }

    printf("\n");



    return 0;

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!