何为大端序,小端序?

何为大端序,小端序?

简单点说,就是字节的存储顺序,如果数据都是单字节的,那怎么存储无所谓了,但是对于多字节数据,比如int,double等,就要考虑存储的顺序了。注意字节序是硬件层面的东西,对于软件来说通常是透明的。再说白一点,字节序通常只和你使用的处理器架构有关,而和编程语言无关,比如常见的Intel x86系列就是小端序。

Big-endian(大端序)

数据的高位字节存放在地址的低端 低位字节存放在地址高端

Little-endian(小端序)

数据的高位字节存放在地址的高端 低位字节存放在地址低端

字节的高位与低位
举个例子,int a = 0x12345678 ; 那么左边12就是高位字节,右边的78就是低位字节,从左到右,由高到低,(注意,高低乃相对而言,比如56相对于78是高字节,相对于34是低字节)

地址的高端与低端
0x00000001
0x00000002
0x00000003
0x00000004
从上倒下,由低到高,地址值小的为低端,地址值大的为高端。

不同字节序如何存储数据?

看看两种方式如何存储数据,假设从地址0x00000001处开始存储十六进制数0x12345678,那么

Bit-endian 如此存放(按原来顺序存储)
0x00000001           – 12
0x00000002           – 34
0x00000003           – 56
0x00000004           – 78

Little-endian 如此存放(颠倒顺序储存)
0x00000001           – 78
0x00000002           – 56
0x00000003           – 34
0x00000004           – 12

一个很好的记忆方法是,大端序是按照数字的书写顺序进行存储的,而小端序是颠倒书写顺序进行存储的。

编程判断大端序和小端序

方法一

复制代码
bool IsBigEndian()
{
    int a =1 ; 
    if(((char*)&a)[3] ==1)
        return true ;
    else
        return false ;
}
复制代码

打开VS的内存窗口,看一下a的存储方式,一目了然

由于a是int,所以占四个字节,其值是00000001,存储方式如下。所以a[3]是0,不是大端序。一个更标准的写法是将a[3]替换为a[sizeof(int) - 1]。

0x0012FE88  01

0x0012FE89  00

0x0012FE8A  00

0x0012FE8B  00

方法二,使用union,原理见后面的面试题。

复制代码
bool IsBigEndian()
{
    union
    {
        unsigned short a ;
        char b ;
    } c;

    c.a =0x0102 ;

    if(c.b ==1)
        return true ;
    else
        return false ;
}
复制代码

一道面试题

来道题巩固一下,下面代码输出什么?

复制代码
union u
{
    int i ;
    char x[2] ;
} a ;

int main(void)
{
    a.x[0] ='1' ;
    a.x[1] ='2' ;

    cout << a.i << endl ;

    getchar() ;
    return 0 ;
}
复制代码

这个题,要看你使用的是什么系列的CPU,姑且假设是Intel系列的。Union是一个特殊的结构,其中所有成员共享结一个内存地址,任意时间只能存储一个成员,上面的Union大小为4个字节,所以上面的代码存储完字符1和2之后,Union的存储貌似应该是0x31320000,31和32分别是字符’1’和’2’的十六进制ASCII码(注意是字符1和2,而不是整数),但是Intel系列的CPU都是按照小端序存储的,所以,正确的顺序是0x00003231,对应的十进制数是12849,你答对了么?

关于字节序的详细内容,请看Wikipedia的介绍 http://en.wikipedia.org/wiki/Endianness

== Happy coding ==

The End

作者: zdd
出处: http://www.cnblogs.com/graphics/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.


<think>嗯,用户现在明确要求理解大端小端序的概念及区别,而且提供了几个站内引用作为补充材料。从对话历史看,用户之前问过BOM(字节顺标记)的相关问题,现在转向底层字节,可能是想深入理解计算机如何处理多字节数据。 用户提供的引用材料很有价值:[^1]用Verilog示例展示内存布局,[^2]给出C语言端转换代码,[^3][^4]则从网络和系统角度解释概念。需要把这些零散信息整合成连贯的体系。 用户身份可能是程员或计算机专业学生——因为引用涉及代码和硬件内存布局。深层需求可能是解决实际编程中的字节问题,比如网络传输或文件解析。需要强调应用场景,避免纯理论。 核心任务:用生活化类比解释抽象概念(比如地址高低位),用可视化内存布局图辅助理解,最后通过检测代码和转换代码落地到实践。要特别注意和之前BOM知识的关联(比如BOM本质就是解决字节问题的标记)。 需要规避的陷阱:1)避免过度深入硬件电路;2)区分字节和位(用户引用[^1]的data[7:0]容易混淆);3)明确网络字节固定为大端的特殊性。 数学表达要求严格:所有公式用$...$包裹,比如端转换函数中的位运算 $\text{0xFF000000}$ 必须规范书写。检测代码段用独立格式呈现。</think>### 大端小端序详解 #### 一、核心定义 1. **大端 (Big-endian)** 高位字节存储在**低内存地址**,低位字节存储在高地址。 $\text{示例:0x12345678 在内存中的存储}$ | 地址 | 数据 | |------|------| | 低地址 | `12` (最高位字节) | | | `34` | | | `56` | | 高地址 | `78` (最低位字节) 符合人类阅读习惯(从左到右由高到低)[^3]。 2. **小端序 (Little-endian)** 低位字节存储在**低内存地址**,高位字节存储在高地址。 $\text{示例:0x12345678 在内存中的存储}$ | 地址 | 数据 | |------|------| | 低地址 | `78` (最低位字节) | | | `56` | | | `34` | | 高地址 | `12` (最高位字节) 符合计算机处理习惯(先处理低位数据)[^1]。 #### 二、核心区别 | 特性 | 大端 | 小端序 | |--------------|----------------------------|----------------------------| | **存储顺** | 高位字节 → 低地址 | 低位字节 → 低地址 | | **地址增长** | 向高位地址存储低位数据 | 向高位地址存储高位数据 | | **优势场景** | 网络传输、人类直接阅读 | CPU计算(如x86/ARM架构) | | **检测方法** | 首字节≠1(见下方代码)[^4] | 首字节=1(见下方代码)[^4] | #### 三、检测系统字节的代码 ```cpp #include <iostream> int main() { int num = 1; // 十六进制 0x00000001 char *ptr = (char*)# if (*ptr == 1) { std::cout << "小端序(低位字节在低地址)" << std::endl; } else { std::cout << "大端(高位字节在低地址)" << std::endl; } return 0; } ``` **原理**:通过检查整型`num=1`的首字节(最低地址)内容: - 小端系统首字节为 `0x01`(输出1) - 大端系统首字节为 `0x00`(输出≠1)[^4] #### 四、端转换的实践代码 网络通信中需统一用**大端(网络字节)**,以下实现32位整数的端转换: ```c #include <stdio.h> unsigned int swap_endian(unsigned int num) { return ((num >> 24) & 0xFF) | // 字节3 → 字节0 ((num << 8) & 0xFF0000) | // 字节1 → 字节2 ((num >> 8) & 0xFF00) | // 字节2 → 字节1 ((num << 24) & 0xFF000000); // 字节0 → 字节3 } /* * 示例:0x12345678 * 大端→小端:0x78563412 */ ``` #### 五、关键应用场景 1. **网络协议** TCP/IP 规定使用**大端**(网络字节),`htonl()`/`ntohl()` 函数用于主机与网络转换[^3]。 2. **文件格式** UTF-16编码文件用BOM(`0xFEFF`大端,`0xFFFE`小端)声明字节[^1]。 3. **硬件设计** Verilog/FPGA开发需显式指定端(如存储器接口)[^1]。 4. **跨平台数据交换** 不同架构设备(ARM小端 vs PowerPC大端)通信时需转换端。 --- ### 相关问题 1. **如何用Python检测系统字节并实现端转换?** 2. **网络编程中为什么强制使用大端?历史原因是什么?[^3]** 3. **RISC-V架构默认采用哪种字节?能否动态切换?** 4. **端转换函数的性能优化方法(如SIMD指令应用)?[^2]** 5. **在分布式系统中,如何设计端自适应传输协议?**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值