little endian和big endian

简而言之:
Big endian machine: It thinks the first byte it reads is the biggest.
Little endian machine: It thinks the first byte it reads is the littlest.
举个例子,从内存地址0x0000开始有以下数据
 0x0000     0x12
 0x0001     0x34
 0x0002     0xab
 0x0003     0xcd
如果我们去读取一个地址为0x0000的四个字节变量,若字节序为big-endian,则读出
结果为0x1234abcd;若字节序位little-endian,则读出结果为0xcdab3412.
如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
                big-endian     little-endian
0x0000     0x12              0xcd
0x0001     0x23              0xab
0x0002     0xab              0x34
0x0003     0xcd              0x12
x86系列CPU都是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;
}



参考资料:<<C: A Reference Manual>>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值