`
youngerbaby
  • 浏览: 115114 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

转载:Endianness一点通

阅读更多

原文:http://packetmania.bokee.com/

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 68000Java Virtual Machine
  • Bi-Endian, 运行Big Endian模式: MIPS运行IRIX, PA-RISC,大多数PowerPowerPC系统
  • Bi-Endian, 运行Little Endian模式: MIPS  运行Ultrix,大多数DEC Alpha, IA-64运行Linux
  • Little Endian: Intel x86AMD64,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
  • 分享到:
    评论

    相关推荐

      endianness.h

      最后跑代码可能出现错误,将文件endianness.h保存C:\Program Files\tesseract\include\leptonica 完整流程可以参考https://editor.csdn.net/md/?articleId=90347165,现在才知道到达100积分后,后面积分都被CSDN私...

      Fast-CDR:eProsima FastCDR库提供两种序列化机制。 一种是标准CDR序列化机制,另一种是更快的实现

      快速CDR eProsima Fast CDR是一个C ++库,提供两种序列化机制。 一种是标准CDR序列化机制,另一种是修改标准的更快实现。 建造 eProsima Fast CDR提供脚本来构建和安装它。 同样在您可以找到使用自动工具Linux...

      Endianness and ARM Processors

      ### 关于ARM处理器的端序性(Endianness)深入解析 #### 概述与定义 在计算机科学领域,端序性(Endianness)是一个关键概念,它指的是多字节数据类型(如整数、浮点数或字符序列)在计算机内存中存储时字节的排列...

      Endianness-Well:基于AC的多线程应用程序

      在IT领域,Endianness是计算机系统中处理数据的一种方式,它涉及到如何在内存或网络传输中存储和解析数据的顺序。"Endianness-Well"可能是某个项目或库的名称,专注于解决多线程环境下关于字节序的问题。本文将深入...

      spice_protocol

      **2.1 字节序(Endianness)** - **定义**:指多字节数据在内存中的存储顺序。 - **Spice Protocol**:规定使用小端序(little-endian)格式存储多字节数据。 **2.2 数据类型(Datatypes)** - **基本类型**:如...

      endian c++大小端编辑

      在计算机科学中,"endianness"是指数据存储的顺序,特别是在多字节数据类型(如整数或浮点数)中。"大端"(Big-endian)和"小端"(Little-endian)是两种主要的字节序类型。大端模式下,数据的最高有效字节存储在...

      DSP软件开发介绍.ppt

      #### 七、Endianness模式 - **Big Endian**: 最重要的字节存储在最低地址中。 - **Little Endian**: 最重要的字节存储在最高地址中。 例如,对于0x12345678: - **Big-Endian**: 0x00: 0x12 | 0x01: 0x34 | 0x02: ...

      ATA8/ATAPI ACS

      ### ATA8/ATAPI ACS详解 #### 一、概述 ATA8/ATAPI ACS(AT Attachment 8 - ATA/ATAPI Command Set)是一项重要的技术标准,由美国国家标准委员会(Accredited Standards Committee INCITS)下属的技术委员会T13...

      在IAR配置中经常遇到的几个错误及解决方法

      - 在`Options for Target`对话框中,选择`C/C++ Compiler`-&gt;`Optimization`选项卡,确保`Endianness`设置正确。 - `Big Endian`: 计算机认为读取的第一个字节是最大的字节。 - `Little Endian`: 计算机认为读取的...

      利用串口传输结构体数据

      字节序(Endianness):大端和小端 二、应用 结构体是一种数据的归类方式,相比数组或变量更具有整体全面性,例如一个数组只可以放一些按照元素顺序存放的单元变量,即 buffer = {x, x, x, x, x…},i 有多大,数组...

      大端(Big Endian)与小端(Little Endian)简介

      ### 大端与小端表示法详解 #### 一、引言 在计算机科学领域,数据的存储方式是一项基础而重要的技术。对于大于255(即超过一个字节)的整数,需要多个字节来进行存储。这些字节如何在内存中排列,涉及到两种主要的...

      AP.rar_endian_大端

      在计算机科学中,"endianness"是一个重要的概念,主要涉及到数据在内存或网络传输中如何存储和解析的问题。"大端"(Big-Endian)和"小端"(Little-Endian)是两种主要的字节序类型,它们决定了多字节数据(如整数或...

      rust-test-assembler:包含一组用于构建复杂二进制流的类型的 Rust crate

      概述 这个 Rust crate 实现了一组用于构建复杂二进制流的类型,主要用于编写对摄取二进制数据的事物的测试。... // `Section`s can be created with either default endianness. let s = Section :: with_endian

      百度最新秋招客户端试题.docx

      - ARM存储类型包括B和D,即little-endianness和big-endianness。 8. **ARMV8处理器特点**: - ARMV8处理器支持巨大的页(hugepage),是64位处理器,支持虚拟化,并且支持secure mode。 9. **二分查找**: - 在...

      IT类专业最全的面试笔试题集合

      - 网络设备和原理:比如芯片的字节存储顺序(endianness)。 4. **逻辑推理和智力题**: - 逻辑门电路:通过与门、或门判断输出结果。 - 无限循环识别:通过for循环的条件判断分析。 5. **软件工程和面试流程**...

      AMBA2.0总线协议中文版

      - **位格式Endianness**:指明数据的字节顺序。 **3.11 总线仲裁机制(重点)** - **信号描述**:用于控制和管理主设备访问总线的信号。 - **总线访问请求**:主设备向仲裁器发送请求以获得总线使用权。 - **总线...

      ARM Instruction Set Quick Reference Card

      - **Endianness**:指数据存储的方式。ARM支持两种格式:Big Endian(高位字节存储在低地址)和Little Endian(低位字节存储在低地址)。 - **Condition Code (cond)**:用于控制指令执行的条件码。例如,EQ表示相等...

      c++题目以及汇编,面试题目

      4. 判断计算机字节存储顺序(endianness): - 可以定义一个包含一个大整数(例如,`0x12345678`)的结构体,然后查看这个整数在内存中的字节顺序。如果低字节在前,则是小端(little endian),反之则是大端(big ...

      C/C++ 大小端判断

      在计算机科学中,"大小端"(Endianness)是指数据在内存或网络传输中存储的顺序。简单来说,就是指多字节数据(如整数或浮点数)是按照高字节优先(Big-Endian)还是低字节优先(Little-Endian)的方式存储的。这个...

      QT下TCP协议实现网路数据传输

      // 可以根据需求选择endianness out (file.size()); // 预先发送文件大小 char buffer[1024]; while (!file.atEnd()) { out.write(buffer, file.read(buffer, sizeof(buffer))); } file.close(); ``` 在客户端,...

    Global site tag (gtag.js) - Google Analytics