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位即一个字节为单位的.
简单的说,ittle endian把低字节存放在内存的低位;而big endian将低字节存放在内存的高位.
现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian.
以下是判断字节存储顺序的可移植的C语言代码:
[Copy to clipboard] [ - ]
CODE:
/********************************************************************
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[i], u.Char[i]);
}
return 0;
}
很多人认为掌握这个知识是不必要,其实不然.在网络编程中,TCP/IP统一采用big endian方式传送数据,也就是说,假设现在是在一个字节顺序是little endian的机器上传送数据,要求传送的数据是0XCEFABOBO,那么你就要以0XBOBOFACE的顺序在unsigned int中存放这个数据,只有这样才能保证存放的顺序满足TCP/IP的字节顺序要求.很多时候,需要自己编写应用层的协议,字节顺序的概念在这个时候就显得及其的重要了.
下面给出的是在big endian和little endian中相互转换的代码,C语言强大的位操作的能力在这里显示了出来:
[Copy to clipboard] [ - ]
CODE:
/********************************************************************
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;
}
参考资料:<<C: A Reference Manual>>
Endianness 的问题实质就是关于计算机如何存储大的数值的问题。
我们知道一个基本存储单元可以保存一个字节,每个存储单元对应一个地址。对于大于十进制255(16进制0xff)的整数,需要多个存储单元。例如,4660对应于0x1234,需要两个字节。不同的计算机系统使用不同的方法保存这两个字节。在我们常用的PC机中,低位的字节0x34保存在低地址的存储单元,高位的字节0x12保存在高地址的存储单元;而在Sun工作站中,情况恰恰相反,0x34位于高地址的存储单元,0x12位于低地址的存储单元。前一种就被称为Little Endian,后一种就是Big Endian。
如何记住这两种存储模式?其实很简单。首先记住我们所说的存储单元的地址总是由低到高排列。对于多字节的数值,如果先见到的是低位的字节,则系统就是Little Endian的,Little 就是"小,少"的意思,也就对应"低"。相反就是Big Endian,这里 Big "大"对应"高"。
为了加深对Endianness的理解,让我们来看下面的C程序例子:
char a = 1;
char b = 2; 地址偏移量 内存映像
short c = 255; /* 0x00ff */ 0x0000: 01 02 FF 00
long d = 0x44332211; 0x0004: 11 22 33 44
在右侧我们可以见到在基于Intel 80x86的系统上的内存映像,显然我们可以马上判定这一系统是Little Endian的。对于16位的整形数(short)c,我们先见到其低位的0xff,下一个才是0x00。同样对于32位长整形数(long)d,在最低的地址0x0004存的是最低位字节0x11。如果是在Big Endian的计算机中,则地址偏移量从0x0000到0x0007的整个内存映像将为:01 02 00 FF 44 33 22 11。
所有计算机处理器都必须在这两种Endian间作出选择。但某些处理器(如MIPS和IA-64)支持两种模式,可由编程者通过软件或硬件设置一种 Endian。以下是一个处理器类型与对应的Endian的简表:
纯Big Endian: Sun SPARC, Motorola 68000,Java Virtual Machine
Bi-Endian, 运行Big Endian模式: MIPS运行IRIX, PA-RISC,大多数Power和PowerPC系统
Bi-Endian, 运行Little Endian模式: MIPS 运行Ultrix,大多数DEC Alpha, IA-64运行Linux
Little Endian: Intel x86,AMD64,DEC VAX
如何在程序中检测本系统的Endianess?可调用下面的函数来快速验证,如果返回值为1,则为Little Endian;为0则是Big Endian:
int testendian() { int x = 1; return *((char *)&x);}
Endianness对于网络通信也很重要。试想当Little Endian系统与Big Endian的系统通信时,如果不做适当处理,接收方与发送方对数据的解释将完全不一样。比如对以上C程序段中的变量d,Little Endian发送方发出11 22 33 44四个字节,Big Endian接收方将其转换为数值0x11223344。这与原始的数值大相径庭。为了解决这个问题,TCP/IP协议规定了专门的"网络字节次序",即无论计算机系统支持何种Endian,在传输数据时,总是数值最高位的字节最先发送。从定义可以看出,网络字节次序其实是对应Big Endian的。
为了避免因为Endianness造成的通信问题,及便于软件开发者编写易于平台移植的程序,特别定义了一些C语言预处理的宏来实现网络字节与主机字节次序之间的相互转换。htons()和htonl()用来将主机字节次序转成网络字节次序,前者应用于16位无符号数,后者应用于32位无符号数。 ntohs()和ntohl()实现反方向的转换。这四个宏的原型定义可参考如下(Linux系统中可在netinet/in.h文件里找到):
#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
#define htons(A) (A)
#define htonl(A) (A)
#define ntohs(A) (A)
#define ntohl(A) (A)
#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#define htons(A) ((((uint16)(A) & 0xff00) >> 8) | \
(((uint16)(A) & 0x00ff) << 8))
#define htonl(A) ((((uint32)(A) & 0xff000000) >> 24) | \
(((uint32)(A) & 0x00ff0000) >> 8) | \
(((uint32)(A) & 0x0000ff00) << 8) | \
(((uint32)(A) & 0x000000ff) << 24))
#define ntohs htons
#define ntohl htohl
#else
#error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."
#endif
分享到:
相关推荐
### Little Endian 和 Big Endian 的概念解释 #### 一、基本定义 在计算机科学领域,数据存储的方式对于数据处理的效率以及程序的兼容性至关重要。其中,Little Endian 和 Big Endian 是两种常见的字节顺序(Byte ...
这些字节如何在内存中排列,涉及到两种主要的存储方式——大端(Big Endian)与小端(Little Endian)。本文将深入探讨这两种存储方式的概念、原理及其应用场景。 #### 二、大端与小端的定义 1. **大端表示法(Big...
nohead data big endian to little endian
### Big Endian与Little Endian详解 #### 一、引言 在计算机科学领域中,数据存储的方式至关重要,尤其是在涉及跨平台数据交换时。本文旨在详细介绍两种常见的数据存储格式:Big Endian(大端模式)与Little Endian...
little endian,big endian 小端存储、大端存储.zip
这里我们主要讨论两种字节顺序:大端字节序(Big-endian)和小端字节序(Little-endian)。这两个术语源自Gulliver's Travels中的两个部落名称,用来形象地描述数据在内存中的排列方式。 标题“Little_Big_endian....
标题中的“Big-and-Little-Endian.rar_LIt_endian_little”可能是指一个压缩包,其中包含了一个名为“Big and Little Endian.pdf”的文件,该文件详细解释了这两种字节序的概念。 大端字节序(Big-Endian)是指数据...
在计算机科学领域,大端(Big Endian)与小端(Little Endian)指的是数据(特别是多字节整数)在内存中存储时的字节顺序。这两种表示方法主要应用于不同类型的计算机体系结构中,对软件开发尤其是跨平台编程具有...
2. Unicode:这是一个标准,定义了所有已知字符的唯一数字表示,分为Little Endian和Big Endian两种字节顺序。Little Endian先存储低字节,Big Endian则先存储高字节。 3. UTF-8:一种变长的Unicode编码,用1到4个...
Endianness 主要分为两种:大端法(Big Endian)和小端法(Little Endian)。这个名为 "Macro-test-mode-test-system.zip_endian_little_endian" 的压缩包文件是为了帮助用户检测他们的个人计算机(PC)使用的是哪种...
基于STM32HAL库,USART-调试串口(大小端测试),对应文章:https://blog.csdn.net/qq_36075612/article/details/115935138?spm=1001.2014.3001.5501
西门子PLC接口,大端和小-Endian的存储格式pdf,西门子PLC接口,大端和小-Endian的存储格式:本文介绍了SINUMERIK:PLC接口,和Little-Endian的Big-Endian的存储格式
大端(Big Endian)与小端(Little Endian)是指计算机系统中多字节数据在内存中的存储方式。这个概念主要涉及到处理器架构和数据表示,对于跨平台编程和网络通信尤其重要。Endianness的问题源于不同的计算机系统...
你是否遇到过,内存中的数据顺序颠倒 你存入1234,实际存储的是3412. 字节存储顺序: little-endian小端,big-endian大端 教程 主机序,网络序 hton,ntoh
本文档描述了TMS320C64x+数字信号处理器Little-Endian DSP Library(DSPLIB),该库提供了大量实用的函数和例程,用于数字信号处理、数据处理和算法实现等领域。 数字信号处理器(DSP) 数字信号处理器(DSP)是一...
目前主要存在两种字节序类型:大端模式(Big Endian)与小端模式(Little Endian)。这两种模式直接影响着程序在不同系统之间的兼容性以及网络通信中数据包的解码。 #### 大端模式(Big Endian) 大端模式是指在多...
buffer ) ) [ 0 ] === 0x04030201 )用法使用 npm 安装: npm install is-little-endian然后像这样使用它: if ( require ( "is-little-endian" ) ) { // Use little endian buffer} else { // Use big endian ...
本篇文章将深入探讨标题中提及的几种字符编码:Text、ANSI、Unicode(包括Little Endian和Big Endian)、UTF-8以及UTF-7,并介绍它们之间的转换。 1. **Text编码**: 在Windows系统中,通常所说的"Text"编码是指...
本资源摘要信息介绍了如何在VC ANSI环境下按行读取四种不同编码格式的文本文件,包括ANSI、UNICODE、UNICODE big endian和UTF-8。通过研究这四种编码方式的特点,设计了一个继承自CStdioFile类的扩展类CStdioFileEx...
常见的有两种字节序:Little Endian(小端字节序)和 Big Endian(大端字节序)。Little Endian 将低序字节存储在起始地址,而 Big Endian 将高序字节存储在起始地址。 Little Endian 最符合人的思维的字节序,因为...