little endian 与 big endian

 
little endian 与 big endian
??????? little endian和big endian是表示计算机字节顺序的两种格式,所谓的字节顺序指的是长度跨越多个字节的数据的存放形式.
? ?? ???假设从地址0x00000000开始的一个字中保存有数据0x1234abcd,那么在两种不同的内存顺序的机器上从字节的角度去看的话分别表示为:
? ?? ? 1)little endian:0xcdab3412,即0x00000000-0xcd,0x00000001-0xab,0x00000002-0x34,0x00000003-0x12
? ?? ? 2)big??endian:0x1234abcd,即0x00000000-0x12,0x00000001-0x34,0x00000002-0xab,0x00000003-0xcd
? ?? ? 需要特别说明的是,以上假设机器是每个内存单元以8位即一个字节为单位的.
? ?? ? 简单的说,little endian把低位存放到高位,而big endian把低位存放到低位.
? ?? ? 现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian.
? ?? ?
? ?? ? 以下是判断字节存储顺序的可移植的C语言代码:



#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[i], u.Char[i]);
? ? }

? ? ? ? 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[i] = data % 256;
? ?? ???// 或者可以:
? ?? ???//cmd[i] = 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[i];? ?? ???
? ? }
? ? ? ?
? ? 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[i]);
? ? }

? ? // 再以相反的顺序保存数据到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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值