大端模式和小端模式

article/2025/9/24 21:50:52

 

一.概念

大端模式(Big-endian):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端,即正序排列,高尾端;

小端模式(Little-endian):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端,即逆序排列,低尾端;

例(无论是小端模式还是大端模式。每个字节内部都是按顺序排列):

1)大端模式:

低地址 -----------------> 高地址

0x0A  |  0x0B  |  0x0C  |  0x0D

2)小端模式:

低地址 ------------------> 高地址

0x0D  |  0x0C  |  0x0B  |  0x0A

3)下面是两个具体例子:

16bit宽的数0x1234在两种模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址小端模式存放内容大端模式存放内容
0x40000x340x12
0x40010x120x34

32bit宽的数0x12345678在两种模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址小端模式存放内容大端模式存放内容
0x40000x780x12
0x40010x560x34
0x40020x340x56
0x40030x120x78

4)大端小端没有谁优谁劣,各自优势便是对方劣势:

小端模式 :强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式 :符号位的判定固定为第一个字节,容易判断正负。

二、数组在大端小端模式下的存储:

以unsigned int num = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示num:
Big-Endian: 低地址存放高位,如下:

低地址

---------------

buf[0] (0x12) -- 高位 

buf[1] (0x34)

buf[2] (0x56)

buf[3] (0x78) -- 低位

---------------
高地址
 
Little-Endian: 低地址存放低位,如下:

低地址

---------------

buf[0] (0x78) -- 低位

buf[1] (0x56)

buf[2] (0x34)

buf[3] (0x12) -- 高位

--------------

高地址

三、为什么会有大小端模式之分呢?

       这是因为在计算机中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8 bit。但是在C 语言中除了 8 bit 的char之外,还有 16 bit 的 short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着如果将多个字节安排的问题。大端存储模式和小端存储模式也就应运而生。例如一个16bit的short型 x ,在内存中的地址为 0x0010,x 的值为0x1122,那么0x11位高字节,0x22位低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

四、如何判断机器的字节序 (重点)

一般都是通过 union 来测试的,下面这段代码可以用来测试一下你的编译器是大端模式还是小端模式:

#include <stdio.h>int main (void)
{
union{
short i;
char a[2];
}u;//联合体uu.a[0] = 0x11;
u.a[1] = 0x22;printf ("0x%x\n", u.i); //0x2211 为小端 0x1122 为大端
return 0;
}输出结果:
0x2211

      union 型数据所占的空间等于其最大的成员所占的空间。对 union 型的成员的存取都是相对于该联合体基地址的偏移量为 0 处开始,也就是联合体的访问不论对哪个变量的存取都是从 union 的首地址位置开始

     联合是一个在同一个存储空间里存储不同类型数据的数据类型。这些存储区的地址都是一样的,联合里不同存储区的内存是重叠的,修改了任何一个其他的会受影响。那么通过强制类型转换,判断其实存储位置,也可以测试大小端了:

#include <stdio.h>int main (void)
{
short i = 0x1122;
char *a = (char*)(&i);printf ("0x%x\n", *(a + 0)); //大端为 0x11 小端为 0x22
printf ("0x%x\n", *(a + 1));
return 0;
}输出结果:
0x22
0x11

五、常见的字节序

一般操作系统都是小端,而通讯协议是大端的。

1)常见CPU的字节序

Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM既可以工作在大端模式,也可以工作在小端模式。

2)常见文件的字节序

Adobe PS – Big Endian
BMP – Little Endian
DXF(AutoCAD) – Variable
GIF – Little Endian
JPEG – Big Endian
MacPaint – Big Endian
RTF – Little Endian

另外,Java和所有的网络通讯协议都是使用Big-Endian的编码。

六、如何进行大小端转换(重点)

第一种方法:位操作

#include<stdio.h>
typedef unsigned int uint_32 ;
typedef unsigned short uint_16 ;//16位
#define BSWAP_16(x) \
(uint_16)((((uint_16)(x) & 0x00ff) << 8) | \ (((uint_16)(x) & 0xff00) >> 8) \)//32位
#define BSWAP_32(x) \
(uint_32)((((uint_32)(x) & 0xff000000) >> 24) | \ (((uint_32)(x) & 0x00ff0000) >> 8) | \
(((uint_32)(x) & 0x0000ff00) << 8) | \ (((uint_32)(x) & 0x000000ff) << 24) \)//无符号整型16位
uint_16 bswap_16(uint_16 x)
{return (((uint_16)(x) & 0x00ff) << 8) | \ (((uint_16)(x) & 0xff00) >> 8) ;
}//无符号整型32位
uint_32 bswap_32(uint_32 x)
{return (((uint_32)(x) & 0xff000000) >> 24) | \ (((uint_32)(x) & 0x00ff0000) >> 8) | \(((uint_32)(x) & 0x0000ff00) << 8) | \ (((uint_32)(x) & 0x000000ff) << 24) ;
}int main(int argc,char *argv[])
{printf("------------带参宏-------------\n");printf("%#x\n",BSWAP_16(0x1234)) ;printf("%#x\n",BSWAP_32(0x12345678));printf("------------函数调用-----------\n");printf("%#x\n",bswap_16(0x1234)) ;printf("%#x\n",bswap_32(0x12345678));return 0 ;
}输出结果:
------------带参宏-------------
0x3412
0x78563412
------------函数调用-----------
0x3412
0x78563412

这里有个思考?上面的哪个是转换为大端,哪个是转为小端了呢?

举个例子,比如数字 0x12 34 56 78在内存中的表示形式为:

1)大端模式:

低地址 -----------------> 高地址

0x12  |  0x34  |  0x56  |  0x78

2)小端模式:

低地址 ------------------> 高地址

0x78  |  0x56  |  0x34  |  0x12

则:

转换为大端:

pPack[2] = (u8)((len >> 8) & 0xFF);
pPack[3] = (u8)(len & 0xFF);

转为为小端:

pPack[2] = (u8)(len & 0xFF);

pPack[3] =  (u8)((len >> 8) & 0xFF);

 

第二种方法:从软件的角度理解端模式,使用 htonl, htons, ntohl, ntohs 等函数

参看:百度百科--htonl ()函数

参看:百度百科--htons ()函数

查看:man htonl

NAME
htonl, htons, ntohl, ntohs - convert values between host and network byte order
SYNOPSIS
#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);DESCRIPTION
The htonl() function converts the unsigned integer hostlong from host byte order to network byte order.The htons() function converts the unsigned short integer hostshort from host byte order to network byte order.The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.The ntohs() function converts the unsigned short integer netshort from network byte order to host byte order.On the i386 the host byte order is Least Significant Byte first, whereas the network byte order, as used on the Internet, is MostSignificant Byte first.

解释

htonl()     //32位无符号整型的主机字节顺序到网络字节顺序的转换(小端->>大端)
htons() 
    //16位无符号短整型的主机字节顺序到网络字节顺序的转换  (小端->>大端)
ntohl()     //32位无符号整型的网络字节顺序到主机字节顺序的转换  (大端->>小端)
ntohs()     //16位无符号短整型的网络字节顺序到主机字节顺序的转换  (大端->>小端)

注,主机字节顺序,X86一般多为小端(little-endian),网络字节顺序,即大端(big-endian);

举两个小例子:

//示例一#include <stdio.h>
#icnlude <arpa/inet.h>int main (void){union{short i;char a[2];}u;u.a[0] = 0x11;u.a[1] = 0x22;printf ("0x%x\n", u.i); //0x2211 为小端 0x1122 为大端printf ("0x%.x\n", htons (u.i)); //大小端转换return 0;
}输出结果:
0x2211
0x1122
//示例二#include <stdio.h>
#include <arpa/inet.h>struct ST{
short val1;
short val2;
};union U{
int val;
struct ST st;
};int main(void)
{
int a = 0;
union U u1, u2;
a = 0x12345678;
u1.val = a;printf("u1.val is 0x%x\n", u1.val);
printf("val1 is 0x%x\n", u1.st.val1);
printf("val2 is 0x%x\n", u1.st.val2);
printf("after first convert is: 0x%x\n", htonl(u1.val));u2.st.val2 = htons(u1.st.val1);
u2.st.val1 = htons(u1.st.val2);
printf("after second convert is: 0x%x\n", u2.val);
return 0;
}输出结果:
u1.val is 0x12345678
val1 is 0x5678
val2 is 0x1234
after first convert is: 0x78563412
after second convert is: 0x78563412

        在对普通文件进行处理也需要考虑端模式问题。在大端模式的处理器下对文件的32,16位读写操作所得到的结果与小端模式的处理器不同。单纯从软件的角度理解上远远不能真正理解大小端模式的区别。事实上,真正的理解大小端模式的区别,必须要从系统的角度,从指令集,寄存器和数据总线上深入理解,大小端模式的区别。 

七.验证当前机器系统的存储方式是大端还是小端

#include <stdio.h>
#include <conio.h>
union Test {short num;char c[sizeof(short)];
};
int main()
{union Test t;t.num = 0x0102;if (t.c[0] == 1 && t.c[1] == 2)printf("大端!\n");else if (t.c[0] == 2 && t.c[1] == 1)printf("小端!\n");elseprintf("未知!\n");getchar();//system("PAUSE"); C函数,C++中需包含头文件#include<stdlib.h>return 0;
}

 


http://chatgpt.dhexx.cn/article/it6DVZ6q.shtml

相关文章

数据存储:大端和小端

目录 字节序 大端和小端 大端小端测试 写入测试 字节码文件的大小端 前面说到&#xff0c;像C/C这类语言编写的程序&#xff0c;它们被编译后&#xff0c;直接转换成了对应平台上的可被CPU直接运行的机器指令&#xff0c;转换之后&#xff0c;原本语言中的数据结构&#x…

大端和小端传输字节序

大端和小端 在计算机中是以字节为单位&#xff0c;每一个地址对应一个字节&#xff0c;一个字节8bit。在C中&#xff0c;除了8bit的char以外&#xff0c;还有16bit的short&#xff0c;32位的int&#xff0c;64位long&#xff0c;当然具体要由编译器决定&#xff0c;可以通过si…

大端字节序和小端字节序

字节序&#xff0c;即字节在电脑中存放时的序列与输入&#xff08;输出&#xff09;时的序列是先到的在前还是后到的在前。 -- 转自&#xff1a;字节序_百度百科 (baidu.com) 在几乎所有的平台上&#xff0c;多字节对象都被存储为连续的字节序列。例如在 C 语言中&#xff0c;一…

简单理解大端小端

大端和小端是计算机写内存的习惯。就如人类写文章时的顺序一般&#xff0c;现代人从左往右&#xff0c;古人却是竖书成行&#xff08;自上而下写满一行后&#xff0c;再自右向左换行。&#xff09;&#xff1b;有些计算机规定从左往右写内存&#xff0c;有些规定从右往左写内存…

java 为什么用大端_Java中的大端和小端

Java整型的字节序是() A.Little-Endian(小端) B.Big-Endian(大端) C.由运行程序的CPU决定 D.由编译程序的CPU决定 对于大小端&#xff0c;我估计肯定有很多开发人员跟我一样都没听过 由于Java是跨平台的&#xff0c;JVM为我们屏蔽了大量的底层细节和复杂性&#xff0c;导致在平…

存储模型:大端和小端

前言&#xff1a; 计算机操作系统中存储信息都是以字节为单位&#xff0c;每个地址单元对应 1 个字节。 1 个字节为 8 bits&#xff0c;对于某些32 位处理器而言&#xff0c;char类型数据占用 1 个字节的空间&#xff0c;short 占用2个字节&#xff0c;int 占用4个字节。而这…

操作系统之大端小端

1. 什么是大端,什么是小端: 所谓的大端模式&#xff0c;是指数据的低位保存在内存的高地址中&#xff0c;而数据的高位&#xff0c;保存在内存的低地址中&#xff1b; 所谓的小端模式&#xff0c;是指数据的低位保存在内存的低地址中&#xff0c;而数据的高位保存在内存的高地…

二进制、16进制、大端小端

16进制的使用 在开发过程中&#xff0c;写文件是常有的事&#xff0c;如果写的内容是文本&#xff0c;随便用一个记事本软件打开即可查看内容是否正确&#xff0c;如果写的是音频文件&#xff0c;就要用音频播放器来查看&#xff0c;如果是视频文件&#xff0c;就要用视频播放…

网络传输大端序_大端、小端与网络字节序

大端(Big-Endian)&#xff0c;小端(Little-Endian)以及网络字节序的概念在编程中经常会遇到。网络字节序(Network Byte Order)一般是指大端(Big-Endian&#xff0c;对大部分网络传输协议而言)传输&#xff0c;大端小端的概念是面向多字节数据类型的存储方式定义的&#xff0c;小…

677-大端模式和小端模式详解

1、大端和小端核心是什么&#xff1f; 大端模式和小端是实际的字节顺序和存储的地址顺序对应关系的两种模式&#xff0c;总结如下&#xff1a; 大端模式&#xff1a;低地址对应高字节 小端模式&#xff1a;低地址对应低字节 不管是大端还是小端模式&#xff0c;我们在读取和存…

大端小端详解

转载&#xff1a;大端小端详解 1>"大端" "小端"的来源 关于大端小端名词的由来&#xff0c;网传有一个有趣的故事&#xff0c;可以追溯到1726年的Jonathan Swift的《格列佛游记》&#xff0c;其中一篇讲到有两个国家因为吃鸡蛋究竟是先打破较大的一端…

大端序发送数据

需要发送数字 151510 大端序发送就是 &#xff1a;00 02 4F D6 string smallData textBox1.Text;//小端数据if (smallData ""){MessageBox.Show("请输入初始里程", "错误",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);textBox1.Text …

c语言之大端小端问题

这就是字节序问题&#xff1a;数据在计算机内存中存储或者网络传输时各字节的存储顺序 通常来说就分为两种情况&#xff1a; 一种是大端(big-endian)&#xff1a;高字节(高位)存放在低地址&#xff0c;低字节(低位)存在高地址 另外一种小端(little-endian)&#xff1a;高位存放…

数据存储:大端小端

文章目录 问题起源大端小端大端小端优劣符合人类阅读方式数据类型转换符号位的识别 参考资料 曾经辨析和了解过大端小端&#xff0c;但是到了实际应用中还是比较模糊。整理一些资料文章&#xff0c;在此记录。 问题起源 在计算机的使用以及现代很多的嵌入式设备中&#xff0c;…

大端与小端

一.大小端介绍 “大端”和“小端”表示多字节值的哪一端存储在该值的起始地址处。小端存储在起始地址处&#xff0c;即是小短字节序&#xff1b;大端存储在起始地址处&#xff0c;即是大端字节序。 大端存储模式&#xff1a;数据的低位保存在内存中的高地址中&#xff0c;数据…

大端和小端的含义及判断代码

1、概述 在计算机系统中&#xff0c;数据都是以字节进行存储的&#xff0c;每个地址单元对应一个字节&#xff0c;每个字节都是8位&#xff08;bit&#xff09;。但是C除了char和bool之外&#xff0c;还有其它多字节类型。怎样存储多字节的数据就分为了大端和小端。字节序只和…

C语言基础 —大端和小端

大端和小端 1、什么是大端和小端2、为什么会有大端和小端3、怎样判断是大端还是小端 1、什么是大端和小端 大端模式&#xff1a;就是 高位字节 存放在内存的 低地址端&#xff0c;低位字节 存放在内存的 高地址端 小端模式&#xff1a;就是 低字节存 放在内存的 低地址端&…

大端和小端的区别和判断

1.概念 大端模式(big endian)&#xff1a;数据的高位字节保存在内存的低地址中&#xff0c;而低位字节保存在内存的高地址中。 小端模式(little endian)&#xff1a;数据的高位字节保存在内存的高地址中&#xff0c;而低位字节保存在内存的低地址中。 问&#xff1a;什么是高…

什么是大端和小端

大端&#xff08;存储&#xff09;模式&#xff1a;是指数据的低位保存在内存的高地址中&#xff0c;而数据的高位保存在低地址中&#xff1b; 小端&#xff08;存储&#xff09;模式&#xff1a;是指数据的低位保存在内存的低地址中&#xff0c;而数据的高位保存在高地址中。 …

大端、小端的前世今生

什么是大端、小端&#xff1f; BigEndian(大端)&#xff1a;低字节在高内存地址 LittleEndian(小端)&#xff1a;低字节在低内存地址 所谓大端小端&#xff0c;也就是看低字节在高内存地址还是低内存地址&#xff0c;也就是看低字节在前还是高字节在前&#xff0c;低字节在前…