大端(Big Endian)与小端(Little Endian)详解

合集下载

大端模式与小端模式理解

大端模式与小端模式理解

⼤端模式与⼩端模式理解字节序字节序指多字节数据在计算机内存储或者⽹络上传输时各字节的顺序。

(来源:百度百科)为了⽅便,逻辑上将字节序列⾥左边的字节称为⾼字节,右边的字节称为低字节,从左到右,由⾼到低,这样符合数学上的思维习惯,左边是⾼位,右边是地位。

⼤端模式与⼩端模式由于每个字节在内存中都是有地址的,并且内存的地址是顺序排列的,当我们在内存中保存数据时:如果,⾼字节存放在低地址,低字节存放在⾼地址,则为⼤端模式(big-endian)。

如果,低字节存放在低地址,⾼字节存放在⾼地址,则为⼩端模式(little-endian)。

数据从内存保存到⽂件(或发送到⽹络上)时,会受到内存的⼤端模式与⼩端模式的影响。

数据从⽂件读取到(或从⽹络接收到)内存时,需要知道之前是先保存的(或是先发送的)⾼字节还是低字节。

C++⽰例代码1//int 占 4 个字节,short 占 2 个字节int main(){printf("在栈上分配内存\n");int a = 0x11223344;short b = 0x5566;short c = 0x7788;unsigned char *pa = (unsigned char *)&a;unsigned char *pb = (unsigned char *)&b;unsigned char *pc = (unsigned char *)&c;printf("pa 0x%p 0x%x\n", pa, a);printf("pb 0x%p 0x%x\n", pb, b);printf("pc 0x%p 0x%x\n", pc, c);printf("按字节序打印所有字节(⾼字节->低字节)\n");printf("a0 0x%x\n", (a & 0xFF000000) >> (3 * 8));printf("a1 0x%x\n", (a & 0x00FF0000) >> (2 * 8));printf("a2 0x%x\n", (a & 0x0000FF00) >> (1 * 8));printf("a3 0x%x\n", (a & 0x000000FF));printf("b0 0x%x\n", (b & 0xFF00) >> (1 * 8));printf("b1 0x%x\n", (b & 0x00FF));printf("c0 0x%x\n", (c & 0xFF00) >> (1 * 8));printf("c1 0x%x\n", (c & 0x00FF));printf("根据地址顺序打印所有字节(低地址->⾼地址)\n");for (int i = 0; i < 4; i++) {printf("pa[%d] 0x%p 0x%02x\n", i, pa + i, pa[i]);}for (int i = 0; i < 2; i++) {printf("pb[%d] 0x%p 0x%02x\n", i, pb + i, pb[i]);}for (int i = 0; i < 2; i++) {printf("pc[%d] 0x%p 0x%02x\n", i, pc + i, pc[i]);}return 0;}⽰例代码1运⾏结果在栈上分配内存pa 0x007ffe24 0x11223344pb 0x007ffe22 0x5566pc 0x007ffe20 0x7788按字节序打印所有字节(⾼字节->低字节)a0 0x11a1 0x22a2 0x33a3 0x44b0 0x55b1 0x66c0 0x77c1 0x88根据地址顺序打印所有字节(低地址->⾼地址)pa[0] 0x007ffe24 0x44pa[1] 0x007ffe25 0x33pa[2] 0x007ffe26 0x22pb[0] 0x007ffe22 0x66pb[1] 0x007ffe23 0x55pc[0] 0x007ffe20 0x88pc[1] 0x007ffe21 0x77⽰例代码1结果分析a、b、c 在内存中的排列情况:---------------------------------------------------|低地址 -> ⾼地址|---------------------------------------------------|....|0x88|0x77|0x66|0x55|0x44|0x33|0x22|0x11|....|---------------------------------------------------a、b、c 是在栈中分配的,可以看到内存地址是连续的,且 a 的地址相对较⾼,c 的地址相对较低。

c语言结构体位域 大小端

c语言结构体位域 大小端

在C语言中,结构体(struct)是一种自定义的数据类型,可以包含多个不同类型的数据成员。

位域(bit-field)是结构体中的一个特殊成员,用于存储固定位数的数据。

位域通常用于紧凑的数据存储,例如在嵌入式系统或低级编程中。

大小端(Endian)是指数据在内存中的存储顺序,分为大端(Big Endian)和小端(Little Endian)两种。

大端模式是指高位字节存储在内存的低地址处,而小端模式是指低位字节存储在内存的低地址处。

在结构体中定义位域时,需要指定每个位域的宽度和顺序,以便确定它们在内存中的布局。

同时,结构体的整体大小也会受到位域的影响。

由于位域是按照字节对齐的,因此如果位域的总宽度不是8的倍数,则会浪费一些空间。

关于大小端问题,对于结构体中的位域,其存储顺序与整型数据相同,即采用系统默认的大小端顺序。

因此,如果需要在不同大小端系统之间移植程序,需要注意位域的存储顺序是否一致。

如果需要确保位域的存储顺序一致,可以使用C标准库中的`#pragma pack`指令来指定结构体的对齐方式。

下面是一个简单的示例代码,演示了如何在C语言中使用结构体和位域:```c#include <stdio.h>struct MyStruct {char a; // 占用1个字节int b : 10; // 占用10个比特(1个字节)int c : 12; // 占用12个比特(1个字节)char d; // 占用1个字节};int main() {struct MyStruct s = {0x0A, 0x3F, 0x4B};printf("a: %x, b: %x, c: %x, d: %x\n", s.a, s.b, s.c, s.d);return 0;}```输出结果将显示`a`, `b`, `c`, `d`的值。

注意,由于系统默认采用大端模式,因此`b`和`c`的值将按照高位字节在前的方式存储和显示。

大端小端(Big-Endian和Little-Endian)

大端小端(Big-Endian和Little-Endian)

大端小端(Big-Endian和Little-Endian)字节序(Endian),大端(Big-Endian),小端(Little-Endian)图文并茂在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。

如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。

目前在各种体系的计算机中通常采用的字节存储机制主要有两种:Big-Endian和Little-Endian,下面先从字节序说起。

一、什么是字节序字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。

其实大部分人在实际的开发中都很少会直接和字节序打交道。

唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。

在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian,引用标准的Big-Endian和Little-Endian的定义如下:a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。

1.1 什么是高/低地址端首先我们要知道我们C程序映像中内存的空间布局情况:在《C专家编程》中或者《Unix环境高级编程》中有关于内存空间布局情况的说明,大致如下图:----------------------- 最高内存地址 0x ffffffff栈底栈栈顶-----------------------NULL (空洞)-----------------------堆-----------------------未初始化的数据----------------------- 统称数据段初始化的数据-----------------------正文段(代码段)----------------------- 最低内存地址 0x00000000以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢?看下图:栈底(高地址)----------buf[3]buf[2]buf[1]buf[0]----------栈顶(低地址)1.2 什么是高/低字节现在我们弄清了高/低地址,接着考虑高/低字节。

大端(Big_Endian)与小端(Little_Endian)简介_百度文库.

大端(Big_Endian)与小端(Little_Endian)简介_百度文库.

大端 (Big Endian与小端 (Little Endian简介Byte Endian 是指字节在内存中的组织 , 所以也称它为 Byte Ordering ,或 Byte Order。

对于数据中跨越多个字节的对象 , 我们必须为它建立这样的约定 :(1 它的地址是多少 ?(2 它的字节在内存中是如何组织的 ?针对第一个问题,有这样的解释 :对于跨越多个字节的对象,一般它所占的字节都是连续的, 它的地址等于它所占字节最低地址。

(链表可能是个例外, 但链表的地址可看作链表头的地址。

比如 : int x, 它的地址为 0x100。

那么它占据了内存中的 Ox100, 0x101, 0x102, 0x103这四个字节(32位系统,所以 int 占用 4个字节。

上面只是内存字节组织的一种情况 : 多字节对象在内存中的组织有一般有两种约定。

考虑一个 W 位的整数。

它的各位表达如下 :[Xw-1, Xw-2, ... , X1, X0],它的 MSB (Most Significant Byte, 最高有效字节为 [Xw-1, Xw-2, ... Xw-8];LSB (Least Significant Byte , 最低有效字节为 [X7, X6, ... , X0]。

其余的字节位于 MSB , LSB之间。

LSB 和 MSB 谁位于内存的最低地址, 即谁代表该对象的地址 ? 这就引出了大端 (Big Endian与小端 (Little Endian的问题。

如果 LSB 在 MSB 前面, 既 LSB 是低地址, 则该机器是小端 ; 反之则是大端。

DEC (Digital Equipment Corporation,现在是 Compaq 公司的一部分和 Intel 的机器(X86平台一般采用小端。

IBM , Motorola(Power PC, Sun的机器一般采用大端。

当然,这不代表所有情况。

有的 CPU 即能工作于小端, 又能工作于大端, 比如ARM , Alpha,摩托罗拉的 PowerPC 。

高位优先与低位优先的比较

高位优先与低位优先的比较

高位优先大端模式和(Big Endian)与地位优先小端模式(Little Endian)简介Byte Endian是指字节在内存中的组织,所以也称它为Byte Ordering,Byte Order。

对于数据中跨越多个字节的对象,我们必须为它建立这样的约定:(1) 它的地址是多少?(2) 它的字节在内存中是如何组织的?针对第一个问题,有这样的解释:对于跨越多个字节的对象,一般它所占的字节都是连续的,它的地址等于它所占字节最低地址。

(链表可能是个例外,但链表的地址可看作链表头的地址)。

比如: int x,它的地址为0x100。

那么它占据了内存中的Ox100,0x101, 0x102, 0x103这四个字节(32位系统,所以int占用4个字节)。

上面只是内存字节组织的一种情况: 多字节对象在内存中的组织有一般有两种约定。

考虑一个W位的整数。

它的各位表达如下:[Xw-1, Xw-2, ... , X1, X0],它的MSB (Most Significant Byte,最高有效字节)为 [Xw-1, Xw-2, ... Xw-8];LSB (Least Significant Byte,最低有效字节)为 [X7,X6,..., X0]。

其余的字节位于MSB, LSB之间。

LSB和MSB谁位于内存的最低地址,即谁代表该对象的地址?PS:内存的最低位置即对象的地址。

这个跟对战的压栈和出栈有关系。

相当于是栈顶指针。

这就引出了大端(Big Endian)与小端(Little Endian)的问题。

如果LSB在MSB前面,既LSB是低地址,则该机器是小端; 反之则是大端。

DEC (Digital Equipment Corporation,现在是Compaq公司的一部分)和Intel 的机器(X86平台)一般采用小端。

IBM, Motorola(Power PC), Sun的机器一般采用大端。

当然,这不代表所有情况。

大小端Big-Endian与Little-Endian

大小端Big-Endian与Little-Endian

⼤⼩端Big-Endian与Little-Endian应该说没做底层开发(硬件或驱动)的⼈很可能不会彻底理解⼤⼩端的概念,⼤⼩端不是简单的⼀句“⼤端在前”还是“⼩端在前”能够概括的问题。

在cpu, 内存, 操作系统, 编译选项, ⽂件,⽹络传输中均有⼤⼩端的概念,这些东西加在⼀起,就很容易把⼈搞晕。

我⾃⼰就晕过很久。

为⽅便说明,再做⼀些定义:(1) 内存可以存储若⼲个单元数据的物理设备,每个单元存储1个字节,每个单元有⼀个地址,其地址线程增长。

为⽅便说明,假设内存地址从0000:0000 ⼀直增加到FFFF:FFFF。

⽤⼀个带箭头的直线表⽰地址的增长⽅向,例如-------------------------->表⽰左边的数据处于低地址,右边的数据处于⾼地址。

(2) U32整型对于unsigned int的变量,计算机是以32bits存储的,即连续的4个字节。

⽐如说,对⼀个值为0x11223344的整数,在内存中的排列⽅式可能为:-------------------------->11 22 33 44 (⼤端)也可能为44 33 22 11 (⼩端)从CPU说起在有了上述定义之后,开始讲⼤⼩端的起源。

这得从CPU说起,我们知道CPU要从内存中加载程序数据来运⾏,CPU要对数字进⾏运算。

那么,CPU在从内存加载4个字节的数据之后,要把它作为⼀个数字来运算。

那它是怎么看待这个数字的呢?-------------------------->11 22 33 44有的CPU认为它是0x11223344,有的CPU认为它是0x44332211。

所以CPU就分为两类:Big-Endian和Little-Endian, 认为它是0x11223344的就是Big-Endian,认为它是0x44332211的就是Little-Endian。

有⼈会为,CPU的“认为”是什么意思。

这其实物理上的电路问题,CPU的所有运算都是通过电路完成,其连接逻辑已经决定了它是按⼤端运算还是按⼩端运算。

什么是大端模式,和小端模式

什么是大端模式,和小端模式

熟练掌握网络字节序的转换
大端转换
当主机A要把数据发送到主机B时,主机A需要把本机的字节 序转换为网络字节序后才能发送。
小端转换
当主机A收到从主机B发送的数据时,主机A需要把网络字节 序转换为本机的字节序后才能处理。
THANKS
感谢观看
模式。
06
大端模式和小端模式对我们 的启示
深入了解计算机存储机制
大端模式一种数据存储方式,其中高位字节保存在内存的低 地址中,而低位字节保存在内存的高地址中。这种存储方式 在机器字长为16位或32位时比较常见,但现在几乎所有的计 算机都是小端模式。
小端模式一种数据存储方式,其中低位字节保存在内存的低 地址中,而高位字节保存在内存的高地址中。这种存储方式 在机器字长为16位或32位时比较常见,但现在几乎所有的计 算机都是小端模式。
什么是大端模式,和小端模 式
xx年xx月xx日
目 录
• 引言 • 大端模式 • 小端模式 • 大端模式和小端模式的差异 • 大端模式和小端模式的判断方法 • 大端模式和小端模式对我们的启示
01
引言
什么是端模式
• 端模式(Endianness)是指计算机系统在处理字节顺序的方 式,也就是多字节数据在内存中如何排列。
存储顺序
在内存中存储数据时,大端模式将数据的每个字节按照由高到低的顺序存储,以 实现数据的正确表示。
大端模式的应用场景
网络通信
在网络通信中,数据的传输通 常是按照大端模式进行的,因 此需要将数据进行字节序的转 换,以确保接收和发送两端的
数据一致性。
文件存储
在某些文件格式中,如网络协 议中的数据包格式,需要按照 大端模式来读取和解析数据。
小端模式的原理

内存中数据存储---大端法(big endian)和小端法(small endian)释疑

内存中数据存储---大端法(big endian)和小端法(small endian)释疑

第一部分基本概念首先不管是大端法还是小端法存储,计算机在内存中存放数据的顺序都是从低地址到高地址,所不同的是首先取低字节的数据存放在低地址还是取高字节数据存放在低地址。

若首先取高字节的数据存放在低地址,则是大端法;若首先取低字节的数据存放在低地址,则是小端法;例如有数据0x (注意:左边是高字节,右边是低字节)大端法存放:存放的地址依次为:0x0001 0x0002 0x0003 0x0004对应的数据依次为:0x010x230x450x67示意图如下:小端法存放:存放的地址依次为:0x0001 0x0002 0x0003 0x0004对应的数据依次为:0x670x450x230x01示意图如下:第二部分判断一个机器是大端存放还是小端法存放知道了大端和小端的定义,我们很容易写代码判断一个机器是大端还是小端:int main(int argc, char* argv[]){union w{int a;char b;}c;c.a = 0x0001;if(c.b==1)printf("small endian\n");else if(c.b==0)printf("big endian\n");elseprintf("error\n");return 0;}注意:之所以可以这样写来判断是因为共用体中所有成员的存放顺序是从低地址开始的用这个程序可以判断intel PC机用的是小端法。

第三部分总结因为我们的思维习惯是从左到右的顺序,所以大端法的存储方式符号我们思维习惯,这因为这个原因,大端法也称为网络编码。

IBM的370主机,多数基于RISC计算机,和Motorola的微处理器使用big endian方法。

TCP/IP也使用big endian方法(big endian方法也叫做网络编码)。

因为我们的语言都是从左到右的习惯方式,所以我们希望存储字符和数字也以同样的方式出现。

大端和小端(BigendianandLittleendian)

大端和小端(BigendianandLittleendian)

⼤端和⼩端(BigendianandLittleendian)⼀、⼤端和⼩端的问题对于整型、长整型等数据类型,Big endian 认为第⼀个字节是最⾼位字节(按照从低地址到⾼地址的顺序存放数据的⾼位字节到低位字节);⽽ Little endian 则相反,它认为第⼀个字节是最低位字节(按照从低地址到⾼地址的顺序存放据的低位字节到⾼位字节)。

例如,假设从内存地址 0x0000 开始有以下数据:0x0000 0x0001 0x0002 0x00030x12 0x34 0xab 0xcd如果我们去读取⼀个地址为 0x0000 的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序为little-endian,则读出结果为0xcdab3412。

如果我们将0x1234abcd 写⼊到以 0x0000 开始的内存中,则Little endian 和 Big endian 模式的存放结果如下:地址 0x0000 0x0001 0x0002 0x0003big-endian 0x12 0x34 0xab 0xcdlittle-endian 0xcd 0xab 0x34 0x12⼀般来说,x86 系列 CPU 都是 little-endian 的字节序,PowerPC 通常是 big-endian,⽹络字节顺序也是 big-endian还有的CPU 能通过跳线来设置 CPU ⼯作于 Little endian 还是 Big endian 模式。

对于0x12345678的存储:⼩端模式:(从低字节到⾼字节)地位地址 0x78 0x56 0x34 0x12 ⾼位地址⼤端模式:(从⾼字节到低字节)地位地址 0x12 0x34 0x56 0x78 ⾼位地址⼆、⼤端⼩端转换⽅法htonl() htons() 从主机字节顺序转换成⽹络字节顺序ntohl() ntohs() 从⽹络字节顺序转换为主机字节顺序Big-Endian转换成Little-Endian#define BigtoLittle16(A) ((((uint16)(A) & 0xff00) >> 8) | (((uint16)(A) & 0x00ff) << 8))#define BigtoLittle32(A) ((((uint32)(A) & 0xff000000) >> 24) | (((uint32)(A) & 0x00ff0000) >> 8) | \(((uint32)(A) & 0x0000ff00) << 8) | (((uint32)(A) & 0x000000ff) << 24))三、⼤端⼩端检测⽅法如何检查处理器是big-endian还是little-endian?C程序:int i = 1;char *p = (char *)&i;if(*p == 1)printf("Little Endian");elseprintf("Big Endian");⼤⼩端存储问题,如果⼩端⽅式中(i占⾄少两个字节的长度)则i所分配的内存最⼩地址那个字节中就存着1,其他字节是0.⼤端的话则1在i的最⾼地址字节处存放,char是⼀个字节,所以强制将char型量p指向i则p指向的⼀定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是⼩端。

大端和小端概念、区别、转换以及辨别方法解析

大端和小端概念、区别、转换以及辨别方法解析

大端和小端概念、区别、转换以及辨别方法解析
大端和小端概念、区别、转换以及辨别方法解析
学习底层编程或逆向的童鞋,肯定对这两个名词并不陌生吧?!今天就给大家介绍一下这两个概念.
科普:
大端和小端,老外叫Big-Endian 和Little-Endian,其实指的都是同一个东东在计算机界,表示数据在存储器中的存放顺序。

不同的CPU、操作系统对待数据的存储方式各有不同,但一般常见的操作系统都是小端,而通讯协议则是大端。

但并不是说系统是小端形式存储,文件就一定要采用小端的形式,不同的应用程序对于自身数据的存储方式也各有千秋(自家数据爱咋放咋放,有些还打乱了加密呢),比如:
* Adobe PS -- 大端
* BMP -- 小端
* GIF -- 小端
* JPEG -- 大端
* MacPaint -- 大端
* RTF -- 小端
那么小端和大端有什么区别呢?举个栗子大家就明了了:
比如0x12345678 这个数:
* 大端法在内存中按字节依次存放为:12 34 56 78
* 小端法在内存中按字节依次存放为:78 56 34 12
解释:
大端:较高的有效字节存放在较低的存储器地址,较低的有效字节存放在较高的存储器地址。

比如整型变量0x12345678 占 4 个字节,那么根据内存地址从小到大它们的存放方式如下:。

字节顺序2143详解

字节顺序2143详解

字节顺序2143详解
字节顺序通常指的是多字节数据在计算机内存中的存储顺序。

有两种主要的字节顺序:大端字节序(Big-Endian)和小端字节序(Little-Endian)。

在多字节值的存储中,大端字节序是将最高位字节存储在最低地址处,而小端字节序是将最高位字节存储在最高地址处。

以一个4字节(32位)整数为例:
•大端字节序:高位字节在前(地址低),低位字节在后(地址高)。

•小端字节序:低位字节在前(地址低),高位字节在后(地址高)。

数字2143在大端和小端字节序下的存储方式如下:
大端字节序(Big-Endian):
yaml
Byte 0: 0x00(00000000)
Byte 1: 0x00(00000000)
Byte 2: 0x43(01000011)
Byte 3: 0x21(00100001)
小端字节序(Little-Endian):
yaml
Byte 0: 0x21(00100001)
Byte 1: 0x43(01000011)
Byte 2: 0x00(00000000)
Byte 3: 0x00(00000000)
在网络通信和数据交换中,为了确保数据的正确解释,必须明确所使用的字节顺序。

有些系统采用大端字节序,有些采用小端字节序,如果不一致,就可能导致数据错误。

因此,在发送和接收数据时,需要了解并匹配目标系统的字节顺序。

Big-Endian与Little-Endian解惑

Big-Endian与Little-Endian解惑

Big-Endian与Little-Endian解惑Big-Endian与Little-Endian解惑最近在研究MPEG2/AVS的过程中,经常会受到大端模式和小端模式在字节存放顺序上的困扰,今天特花时间对其进行了一番琢磨。

大端模式是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;小端模式是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

对于TS流、PS流、Video/Audio的编码数据等都是以大端模式进行数据存放的,而我们一般的PC机是以小端模式存放数据的。

例如:AVS sequence header startcode为0x000001B0由于比特流是采用大端模式,所以它在比特流中的字节存放顺序为:00 00 01 B0我们从比特流中读取这4个字节组成32位的startcode,由于我们的PC采用的是小端模式,所以数据值为0xB0010000,为了与真实的startcode一致,需要进行字节交换来得到0x000001B0如果我们要将0x000001B0以大端模式写入到buffer中,则:DWORD sequencehead[1];sequencehead[0] = 0xB0010000; //因为PC还是以小端模式来存放0xB0010000内存地址对齐及大小端我们常常看到“alignment", "endian"之类的字眼, 但很少有C语言教材提到这些概念. 实际上它们是与处理器与内存接口, 编译器类型密切相关的.考虑这样一个例子: 两个异构的CPU进行通信, 定义了这样一个结构来传递消息:struct Message{short opcode;char subfield;long message_length;char version;short destination_processor;}message;用这样一个结构来传递消息貌似非常方便, 但也引发了这样一个问题: 若这两种不同的CPU对该结构的定义不一样, 两者就会对消息有不同的理解. 有可能导致二义性. 引起二义性的原因有下列两点:1.内存地址对齐2.大小端定义本文先介绍内存地址对齐和大小端的概念, 再回头来看这个例子就豁然开朗了.内存地址对齐洋名叫做" Byte Alignment".大部分16位和32位的CPU不允许将字或者长字存储到内存中的任意地址. 比如Motorola 68000不允许将16位的字存储到奇数地址中, 将一个16位的字写到奇数地址将引发异常.实际上, 对于c中的字节组织, 有这样的对齐规则:•单个字节(char)能对齐到任意地址•2字节(short)以2字节边界对齐•4字节(int, long)以4字节边界对齐为什么会有上述的限制呢? 理解了内存组织, 就会清楚了。

大端存储模式和小端存储模式

大端存储模式和小端存储模式

⼤端存储模式和⼩端存储模式CPU存储数据操作的最⼩单位是⼀个字节。

⼤端存储模式(Big-Endian),⼩端存储模式(Little-Endian)是常见的⼆种字节序。

Little-Endian:低位字节排放在内存的低地址端,⾼位字节排放在内存的⾼地址端。

Big-Endian:⾼位字节排放在内存的低地址端,低位字节排放在内存的⾼地址端。

⽐如0x12345678在内存中的表⽰形式为:采⽤⼤端模式:低地址 --------------------> ⾼地址0x12 | 0x34 | 0x56 | 0x78采⽤⼩端模式:低地址 --------------------> ⾼地址0x78 | 0x56 | 0x34 | 0x12也就是说Big-Endian是指低地址存放最⾼有效字节(MSB),⽽Little-Endian则是低地址存放最低有效字节(LSB)。

⼀般操作系统采⽤的都是⼩端模式,⽽通讯协议采⽤⼤端模式。

1)常见的CPU的字节序Big-Endian : PowerPC,IBM,SunLittle-Endian:x86ARM既可以⼯作在⼤端模式,也可以⼯作在⼩端模式。

2)常见的⽂件的字节序Adobe PS : Big-EndianBMP :Little-EndianGIF : Little-EndianJPEG:Big-Endian此外Java和所有的⽹络通信协议都是使⽤⼤端模式的编码事实上存在字节序,也存在⽐特序。

CPU存储⼀个字节的数据时其字节内的8个⽐特之间的顺序也有Big-Endian和Little-Endian之分。

⽐如字节0xA0的存储格式如下:Big-EndianMSB LSB-------------------------------->1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |Little-EndianLSB MSB-------------------------------->0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |实际上,由于CPU存储数据操作的最⼩单位是⼀个字节,其内部的⽐特序是什么样对我们的程序来说是⼀个⿊盒⼦,也就是说,你给我⼀个指向0xA0这个数的指针,对于Big-Endian⽅式的CPU来说,它是从左往右依次读取这个数的8个⽐特;⽽对于Little-Endian⽅式的CPU来说,则正好相反,是从右往左依次读取这个数的8个⽐特。

Littleendian和Bigendian的区别

Littleendian和Bigendian的区别

Littleendian和Bigendian的区别
许多嵌⼊式系统程序员对Little endian和Big endian模式的概念模糊不清,其实Little endian和Big endian是多字节寻址的微处理器中,两种数据书写和存储顺序的排列⽅式(格式)。

1、Little endian:多字节数据中,书写时字节从右向左排列(MSB…LSB),存储时⾼位地址存放⾼位数据(MSB)。

Little endian是最常⽤的模式,其书写格式(例如“反汇编”出来的源代码)与传统的⼗进制和⼆进制数据的书写格式相同,现在主流微处理器,包括8051系列单⽚机、Intel 8x86 CPU等都采⽤这种模式。

2、Big endian:多字节数据中,书写时字节从左向右排列(LSB…MSB),存储时⾼位地址存放低位数据(LSB)。

Big endian模式仅Motorolra(现为Freescale)等少数⼏个公司的CPU采⽤。

TI公司的DSP通过配置可以选⽤Little endian和Big endian两种模式,但通常都配置为Little endian模式。

假设从地址0x0000开始保存有数据0xEF23(或0EF23H)。

●Little endian模式:书写表达:0xEF23,在内存中的存放顺序是0x0000-0x23, 0x0001-0xEF。

●Big endian模式:书写表达:0x23EF,在内存中的存放顺序是0x0000-0xEF, 0x0001-0x23。

需要特别说明的是, 以上假设系统是每个内存单元以8位即⼀个字节为单位的。

简单的说, Little endian把低字节存放在内存的低位;⽽Big endian将低字节存放在内存的⾼位。

Big- Endian和Little-Endian

Big- Endian和Little-Endian

Big- Endian和Little-Endian在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。

如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。

目前在各种体系的计算机中通常采用的字节存储机制主要有两种:Big-Endian和Little-Endian,下面先从字节序说起。

一、什么是字节序字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。

其实大部分人在实际的开发中都很少会直接和字节序打交道。

唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。

在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian,引用标准的Big-Endian和Little-Endian的定义如下:a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

c)网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。

1.1什么是高/低地址端首先我们要知道我们C程序映像中内存的空间布局情况:在《C专家编程》中或者《Unix环境高级编程》中有关于内存空间布局情况的说明,大致如下图:-----------------------最高内存地址0xffff栈底栈栈顶-----------------------NULL (空洞)-----------------------堆-----------------------未初始化的数据-----------------------统称数据段初始化的数据-----------------------正文段(代码段)-----------------------最低内存地址0x0000以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢?看下图:栈底(高地址)----------buf[3]buf[2]buf[1]buf[0]----------栈顶(低地址)1.2什么是高/低字节现在我们弄清了高/低地址,接着考虑高/低字节。

大小端模式——精选推荐

大小端模式——精选推荐

⼤⼩端模式什么是⼤⼩端模式(1)⼤端模式(big endian)和⼩端模式(little endian)(2)在计算机通信发展起来后,遇到⼀个问题就是:在串⼝通信中,⼀次只能发送⼀个字节。

如果要发送⼀个int类型的数据就会有⼀个问题。

int类型有四个字节,我是按照byte0 byte1 byte2 byte3这样的⽅式发送,还是按照byte3 byte2 byte1 byte0这样的顺序发送。

规则就是发送⽅和接收⽅必须按照同样的字节顺序来通信,否则就会出现错误。

(3)现在所说的⼤⼩端模式,更多的是指计算机存储系统的⼤⼩端。

因为存储系统是32位的,但是数据仍然是按照字节为单位的。

于是乎⼀个32位的⼆进制在内存存储时有2种分布⽅式:⾼字节对应低地址(⼤端模式)、⾼字节对应⾼地址(⼩端模式)(4)所以我们在写代码时,当不知道当前环境是⽤⼤端模式还是⼩端模式的时候,就需要⽤代码来检测当前系统的⼤⼩端。

1 #include <stdio.h>2//共⽤体中很重要的⼀点:a和b都是从u1的低地址开始的。

3 union myunion4 {5int a;6char b;7 };8int is_little_endian(void)9 {10 union myunion u1;11 u1.a = 1; //地址0的那个字节,⼩端模式会放1,⼤端模式会放012return u1.b;13 }14int is_little_endian2(void)15 {16int a = 1;17char b = *(char *)(&a); //指针⽅式是共⽤体⽅式的本质18return b;19 }20int main(void)21 {22int i = is_little_endian();23if(i == 1)24 {25 printf("⼩端模式.\n");26 }27else28 {29 printf("⼤端模式.\n");30 }31 }。

详解大端模式和小端模式

详解大端模式和小端模式

一、大端模式和小端模式的起源关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。

战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。

然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。

据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。

这个其实讽刺当时英国和法国之间持续的冲突。

Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。

二、什么是大端和小端Big-Endian和Little-Endian的定义如下:1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:1)大端模式:低地址-----------------> 高地址0x12 | 0x34 | 0x56 | 0x782)小端模式:低地址------------------> 高地址0x78 | 0x56 | 0x34 | 0x12可见,大端模式和字符串的存储模式类似。

3)下面是两个具体例子:16bit宽的数0x1234在Little-endian模式(以及Big-endian 模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:32bit宽的数0x12345678在Little-endian模式以及Big-endian 模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:4)大端小端没有谁优谁劣,各自优势便是对方劣势:小端模式:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。

数据在内存中存储的方式:大端模式与小端模式

数据在内存中存储的方式:大端模式与小端模式

数据在内存中存储的⽅式:⼤端模式与⼩端模式以下内容⼤多数来⾃百度百科,很容易理解的.什么是⼤端模式,什么是⼩端模式?所谓的⼤端模式(Big-endian),是指数据的⾼字节,保存在内存的低地址中,⽽数据的低字节,保存在内存的⾼地址中,这样的存储模式有点⼉类似于把数据当作字符串顺序处理:地址由⼩向⼤增加,⽽数据从⾼位往低位放;所谓⼩端模式(Little-endian), 是指数据的⾼字节保存在内存的⾼地址中,⽽数据的低字节保存在内在的低地址中,这种存储模式将地址的⾼低和数据位权有效结合起来,⾼地址部分权值⾼,低地址部分权值低,和我们的逻辑⽅法⼀致;为什么有⼤⼩端之分:因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为 8bit。

但是在C语⾔中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的),另外,对于位数⼤于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度⼤于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。

因此就导致了⼤端存储模式和⼩端存储模式。

我们常⽤的X86结构是⼩端模式,⽽KEIL C51则为⼤端模式。

很多的ARM,DSP都为⼩端模式。

有些ARM处理器还可以由硬件来选择是⼤端模式还是⼩端模式。

⽤图来形象地说明⼀下:如何检测⾃⼰电脑是⼤端还是⼩端模式:输⼊以下程序,即可以检测:#include<stdio.h>int main(){short int x;char x0, x1;x = 0x1122;x0 = *((char *)&x); //把x的低位地址的值赋给x0;x1 = *((char *)&x + 1); //把x的⾼位地址的值赋给x1;if( x0 == 0x11 && x1 == 0x22)printf(" This is big-endian \n");else if( x0 == 0x22 && x1 == 0x11)printf("This is little-endian \n");elseprintf("呵呵,你这个⽅法有误啊\n");return0;}如何把数据转换呢??具体要看数据是如何存储的啦,以我遇到的⼀个问题为例,在中,60000张训练图⽚的⽂件为:train-labels-idex1-ubyte.⾸先说明的是它的存储格式为⼤端模式,⽽我的计算机为⼩端模式,那我怎么办??我们⾸先要做的就是知道它内部是如何存放数据的,即多少个字字为⼀个数据单位.我现在有在matlab读取⽂件的源代码,如下:function images = loadMNISTImages(filename)%loadMNISTImages returns a 28x28x[number of MNIST images] matrix containing%the raw MNIST imagesfp = fopen(filename, 'rb');assert(fp ~= -1, ['Could not open ', filename, ''])magic = fread(fp, 1, 'int32', 0, 'ieee-be')assert(magic == 2051, ['Bad magic number in ', filename, ''])numImages = fread(fp, 1, 'int32', 0, 'ieee-be');numRows = fread(fp, 1, 'int32', 0, 'ieee-be');numCols = fread(fp, 1, 'int32', 0, 'ieee-be');images = fread(fp, inf, 'unsigned char');images = reshape(images, numCols, numRows, numImages);images = permute(images,[213]);fclose(fp);% Reshape to #pixels x #examplesimages = reshape(images, size(images, 1) * size(images, 2), size(images, 3));% Convert to double and rescale to [0,1]images = double(images) / 255;end从上⾯我们可以看出⽂件的开头为4个 int32 类型的数,后⾯就是 unsigned char类型的数. 所以得出:int32 占4个字节即32个bit, ⽂件的前 4 * 4个字节需要由⼤端模式转为⼩端模式,⽽后⾯的unsigned char 类型数据本⾝占8 个bit, 不需要转换.以下是如何读取⽂件的源代码:#include<stdio.h>#include<stdlib.h>int main(){int temp, i, nClose;int num1[4]; //⽤于存放前四个int32的数;unsigned char num2[1000]; //⽤于存放读出的1000个unsigned char类型的数;FILE *fp;fp = fopen("train-images-idx3-ubyte","rb");if ( NULL == fp ){printf("Open file error");exit(-1);}fread(num1, 4, 4, fp); //读取前4个int32类型的数据;for(i=0; i<4; i++){ // 由⼤端模式转换为⼩端模式,其实对于占4个字节的数据来说,由⼩端转⼤端,也是⼀样的代码;temp = (num1[i]>>24 & 0x000000FF) | (num1[i] >> 8 & 0x0000FF00) | (num1[i] << 8 & 0x00FF0000 ) | (num1[i] << 24 & 0xFF000000);num1[i] = temp;}fread(num2, 1, 1000, fp); //读取1000个char类型的数据;for(i=0; i<4; i++) //输出4个数;printf(" %d\n", num1[i]);for(i=0; i<1000; i++) // 输出1000个数;printf("%d ", num2[i]);nClose = fclose(fp); // 关闭⽂件;if(EOF == nClose){printf("Close file Error\n");exit(-1);}return0;}最再补充⼀个转换32位的更精简的⽅法,直接上代码(2016年11.28补充),可以由⼤端转为⼩端,也可以由⼩端转为⼤端:uint32_t swap_endian(uint32_t val) {val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);return (val << 16) | (val >> 16);}更新⼀个检测⼤端还是⼩端的代码(来⾃linux内核设计与实现⼀书, 2019-06-19)int x = 1;if (*(char*) &x == 1)printf("⼩端");elsepirntf("⼤端");Reference:部分来⾃百度百科,两张截图来⾃。

Big-Endian和Little-Endian两者概念的区别

Big-Endian和Little-Endian两者概念的区别

Big-Endian和Little-Endian两者概念的区别PS:看了下面各位的讨论后,对字节顺序有了一点了解,因为之前为此问题困扰过。

Intel沿用的是Little-Endian,即低字节在前,高字节在后。

而我所处理的通讯中,是高字节在前,低字节在后。

接收后数据总不对。

后来才发现是对Big-Endian 和 Little-Endian 了解不够。

再网上查阅了很多资料(包括中英版的MSDN),反复体会,才基本弄明白一些Big-Endian和Little-Endian的含义,先总结如下:Big-Endian 和 Little-Endian 字节排序必须注意的是:表中一个Word的长度是16位,一个Byte的长度是8位。

如果一个数超过一个Word的长度,必须先按Word分成若干部分,然后每一部分(即每个Word内部)按Big-Endian或者Little-Endian的不同操作来处理字节。

一个例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为big-endian little-endian0x0000 0x12 0xcd0x0001 0x34 0xab0x0002 0xab 0x340x0003 0xcd 0x12(注意:0xab换算成2进制是10101011,是个8位的数。

我刚才居然当成4位了,自己把自己搞晕了,shit。

)-----------疑问:为什么要以一个Word为基础单位来分割而不是一个DoubleWord或者Byte?究竟就是这么定义的还是跟具体的CPU有关,跟具体的模式(比如说16位模式、32位模式、64位模式的LE和BE定义会不同)有关?我实在是不清楚,望知道的大侠不吝指点,也希望有这方面资料(文章、代码)的朋友贴一些上来。

posted on 2005-02-22 23:59 乾坤一笑周星星顶gyshen所说的,big endian的意思就是高位在前,低位在后,little endian则相反,哪有什么“必须先按Word分成若干部分”的说法,int16如是,int32、int64也如是,float如是,double也如是。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

大端(Big Endian)与小端(Little Endian)详解大端(Big Endian)与小端(Little Endian)简介///////////////////////////////////////////////////////1. 你从哪里来?端模式(Endian)的这个词出自Jonathan Swift书写的《格列佛游记》。

这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big Endian,从尖头开始将鸡蛋敲开的人被归为Littile Endian。

小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。

在计算机业Big Endian和Little Endian也几乎引起一场战争。

在计算机业界,Endian表示数据在存储器中的存放顺序。

采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。

下文举例说明在计算机中大小端模式的区别。

//////////////////////////////////////////////////////2. 读书百遍其义自见小端口诀: 高高低低-> 高字节在高地址, 低字节在低地址大端口诀: 高低低高-> 高字节在低地址, 低字节在高地址long test = 0x313233334;小端机器:低地址-->高地址00000010: 34 33 32 31 -> 4321大端机器:低地址-->高地址00000010: 31 32 33 34 -> 4321test变量存储的是的0x10这个地址,那编译器怎么知道是读四个字节呢? -> 根据变量test的类型long可知这个变量占据4个字节.那编译器怎么读出这个变量test所代表的值呢? -> 这就根据是little endian 还是big endian来读取所以, 小端, 其值为0x31323334; 大端, 其值为0x34333231htonl(test) 的情况: ->其值为: 0x34333231小端机器:00000010: 31 32 33 34 -> 1234大端机器:00000010: 34 33 32 31 -> 4321//////////////////////////////////////////////////////////////////////////// /////////3. 拿来主义Byte Endian是指字节在内存中的组织,所以也称它为Byte Ordering,或Byte Order。

对于数据中跨越多个字节的对象,我们必须为它建立这样的约定:(1) 它的地址是多少?(2) 它的字节在内存中是如何组织的?针对第一个问题,有这样的解释:对于跨越多个字节的对象,一般它所占的字节都是连续的,它的地址等于它所占字节最低地址。

(链表可能是个例外,但链表的地址可看作链表头的地址)。

比如: int x,它的地址为0x100。

那么它占据了内存中的Ox100,0x101,0x102,0x103这四个字节(32位系统,所以int占用4个字节)。

上面只是内存字节组织的一种情况: 多字节对象在内存中的组织有一般有两种约定。

考虑一个W位的整数。

它的各位表达如下:[Xw-1,Xw-2, ... ,X1,X0],它的MSB (Most Significant Byte,最高有效字节)为[Xw-1,Xw-2, ... Xw-8];LSB (Least Significant Byte,最低有效字节)为[X7,X6,...,X0]。

其余的字节位于MSB,LSB之间。

LSB和MSB谁位于内存的最低地址,即谁代表该对象的地址?这就引出了大端(Big Endian)与小端(Little Endian)的问题。

如果LSB在MSB前面,既LSB是低地址,则该机器是小端; 反之则是大端。

DEC (Digital Equipment Corporation,现在是Compaq公司的一部分)和Intel的机器(X86平台)一般采用小端。

IBM,Motorola(Power PC),Sun的机器一般采用大端。

当然,这不代表所有情况。

有的CPU即能工作于小端,又能工作于大端,比如ARM,Alpha,摩托罗拉的PowerPC。

具体情形参考处理器手册。

具体这类CPU是大端还是小端,应该和具体设置有关。

(如,Power PC支持little-endian字节序,但在默认配置时是big-endian 字节序)一般来说,大部分用户的操作系统(如windows, FreeBsd,Linux)是Little Endian的。

少部分,如MAC OS ,是Big Endian 的。

所以说,Little Endian还是Big Endian与操作系统和芯片类型都有关系。

因此在一个处理器系统中,有可能存在大端和小端模式同时存在的现象。

这一现象为系统的软硬件设计带来了不小的麻烦,这要求系统设计工程师,必须深入理解大端和小端模式的差别。

大端与小端模式的差别体现在一个处理器的寄存器,指令集,系统总线等各个层次中。

Linux系统中,你可以在/usr/include/中(包括子目录)查找字符串BYTE_ORDER(或_BYTE_ORDER, __BYTE_ORDER),确定其值。

BYTE_ORDER中文称为字节序。

这个值一般在endian.h或machine/endian.h文件中可以找到,有时在feature.h中,不同的操作系统可能有所不同。

【用函数判断系统是Big Endian还是Little Endian】enum {FALSE = 0, TRUE = !FALSE};typedef short BOOL;BOOL IsBig_Endian()//如果字节序为big-endian,返回true;//反之为little-endian,返回false{unsigned short test = 0x1122;if(*( (unsigned char*) &test ) == 0x11)return TRUE;elsereturn FALSE;}//IsBig_Endian()//////////////////////////////////////////////////////////////////////////// //可以做个实验在windows上下如下程序#include <stdio.h>#include <assert.h>void main( void ){short test;FILE* fp;test = 0x3132; //(31ASIIC码的’1’,32ASIIC码的’2’)if ((fp = fopen ("c:\\test.txt", "wb")) == NULL)assert(0);fwrite(&test, sizeof(short), 1, fp);fclose(fp);}然后在C盘下打开test.txt文件,可以看见内容是21,而test等于0x3132,可以明显的看出来x86的字节顺序是低位在前.如果我们把这段同样的代码放到(big-endian)的机器上执行,那么打出来的文件就是12.这在本机中使用是没有问题的.但当你把这个文件从一个big- endian机器复制到一个little-endian 机器上时就出现问题了.如上述例子,我们在big-endian的机器上创建了这个test文件,把其复制到little-endian的机器上再用fread读到一个short里面,我们得到的就不再是0x3132而是0x3231了,这样读到的数据就是错误的,所以在两个字节顺序不一样的机器上传输数据时需要特别小心字节顺序,理解了字节顺序在可以帮助我们写出移植行更高的代码.正因为有字节顺序的差别,所以在网络传输的时候定义了所有字节顺序相关的数据都使用big-endian,BSD的代码中定义了四个宏来处理:#define ntohs(n) //网络字节顺序到主机字节顺序n代表net, h代表host, s代表short#define htons(n) //主机字节顺序到网络字节顺序n代表net, h代表host, s代表short#define ntohl(n) //网络字节顺序到主机字节顺序n代表net, h代表host, s代表long#define htonl(n) //主机字节顺序到网络字节顺序n代表net, h代表host, s代表long举例说明下这其中一个宏的实现:#define sw16(x) \((short)( \(((short)(x) & (short)0x00ffU) << 8) | \(((short)(x) & (short)0xff00U) >> 8) ))这里实现的是一个交换两个字节顺序.其他几个宏类似.我们改写一下上面的程序#include <stdio.h>#include <assert.h>#define sw16(x) \((short)( \(((short)(x) & (short)0x00ffU) << 8) | \(((short)(x) & (short)0xff00U) >> 8) ))#define sw32(x) \((long)( \(((long)(x) & (long)0x000000ff) << 24) | \(((long)(x) & (long)0x0000ff00) << 8) | \(((long)(x) & (long)0x00ff0000) >> 8) | \(((long)(x) & (long)0xff000000) >> 24) ))// 因为x86下面是低位在前,需要交换一下变成网络字节顺序#define htons(x) sw16(x)#define htonl(x) sw32(x)void main( void ){short test;FILE* fp;test = htons(0x3132); //(31ASIIC码的’1’,32ASIIC码的’2’)if ((fp = fopen ("c:\\test.txt", "wb")) == NULL)assert(0);fwrite(&test, sizeof(short), 1, fp);fclose(fp);}如果在高字节在前的机器上,由于与网络字节顺序一致,所以我们什么都不干就可以了,只需要把#define htons(x) sw16(x)宏替换为#define htons(x) (x).一开始我在理解这个问题时,总在想为什么其他数据不用交换字节顺序?比如说我们write一块buffer到文件,最后终于想明白了,因为都是unsigned char 类型一个字节一个字节的写进去,这个顺序是固定的,不存在字节顺序的问题【大端(Big Endian)与小端(Little Endian)简介】Byte Endian是指字节在内存中的组织,所以也称它为Byte Ordering,或Byte Order。

相关文档
最新文档