大小端序转换

  在嵌入式开发中,经常碰到因端序使用不当导致的错误,故决定决定将工作中常见的转序函数进行梳理,一是为了避免犯同样的错误,二是为了以后方便查询。本文分为四个部分:1、什么是大小端序;2、大小端序数据相互转换函数;3、应用场景;4、使用总结。

  1、什么是大小端序

  大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。

  小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

  现在,以一个unsigned int整型数据0x12345678为例,其大端序、小端序的存储内容如图所示。

  

  2、大小端序数据相互转换函数

  a)将unsigned char数组转换成“大端序”整数;

/*
*    Function:        ConverseArrayToBeUI
*    Description:    将无符号字符数组数据转换成“大端序”整数
*    Parameter:        srcArray    --[in]    源数组数据
*                    desBeData    --[out]    目标“大端序”整数
*    Return            0    成功
*                    非0    失败
*    Note:
*    Other:
*/
int MULCONVERSE_CALL ConverseArrayToBeUI(unsigned char *srcArray,unsigned int *desBeData)
{
    if (srcArray == NULL_POINT || desBeData == NULL_POINT)
    {
        return ERR_NULL_POINT;
    }
    *desBeData = (unsigned int)(srcArray[0]<<24) + (unsigned int)(srcArray[1]<<16) +
                    (unsigned int)(srcArray[2]<<8) + (unsigned int)srcArray[3];
    return _SUCCESS;
}

  b)将unsigned char数组转换成“小端序”整数;

/*
*    Function:        ConverseArrayToLeUI
*    Description:    将无符号字符数组数据转换成“小端序”整数
*    Parameter:        srcArray    --[in]    源数组数据
*                    desLeData    --[out]    目标“小端序”整数
*    Return            0    成功
*                    非0    失败
*    Note:
*    Other:
*/
int MULCONVERSE_CALL ConverseArrayToLeUI(unsigned char *srcArray,unsigned int *desLeData)
{
    if (srcArray == NULL_POINT || desLeData == NULL_POINT)
    {
        return ERR_NULL_POINT;
    }
    *desLeData = (unsigned int)(srcArray[3]<<24) + (unsigned int)(srcArray[2]<<16) +
                    (unsigned int)(srcArray[1]<<8) + (unsigned int)srcArray[0];
    return _SUCCESS;
}

  c)将整数按照“大端序”格式存储在数组中;

/*
*    Function:        ConverseUItoBeArray
*    Description:    将无符号整数转换成“大端序”存储的无符号字符数组
*    Parameter:        srcData        --[in]    源整数
*                    desBeArray    --[out]    目标“大端序”存储的数组数据
*    Return            0    成功
*                    非0    失败
*    Note:
*    Other:
*/
int MULCONVERSE_CALL ConverseUItoBeArray(unsigned int srcData,unsigned char *desBeArray)
{
    if (desBeArray == NULL_POINT)
    {
        return ERR_NULL_POINT;
    }
    desBeArray[0] = (unsigned char)(srcData>>24);
    desBeArray[1] = (unsigned char)(srcData>>16);
    desBeArray[2] = (unsigned char)(srcData>>8);
    desBeArray[3] = (unsigned char)srcData;
    return _SUCCESS;
}

  d)将整数按照“小端序”格式存储在数组中。

/*
*    Function:        ConverseUItoLeArray
*    Description:    将无符号整数转换成“小端序”存储的无符号字符数组
*    Parameter:        srcData        --[in]    源整数
*                    desLeArray    --[out]    目标“小端序”存储的数组数据
*    Return            0    成功
*                    非0    失败
*    Note:
*    Other:
*/
int MULCONVERSE_CALL ConverseUItoLeArray(unsigned int srcData,unsigned char *desLeArray)
{
    if (desLeArray == NULL_POINT)
    {
        return ERR_NULL_POINT;
    }
    desLeArray[3] = (unsigned char)(srcData>>24);
    desLeArray[2] = (unsigned char)(srcData>>16);
    desLeArray[1] = (unsigned char)(srcData>>8);
    desLeArray[0] = (unsigned char)srcData;
    return _SUCCESS;
}

  3、应用场景

  PC(小端序)向芯片(大端序)发送数据

  假设PC产生一个整数数值0x00000001,经通信接口(比如串口)向芯片发送数据时,按照一次发一字节的方式传输数据,那么此时芯片就会收到4字节数据,其内容按照地址从低到高排序为0x01,0x00,0x00,0x00,那么芯片就会认为自己收到的整数数值为0x01000000。

  此时,两个硬件平台就会因为大小端的不同造成数据收发错误,此时解决的方法有两种:1、PC发送数据之前,通过转换函数ConverseUItoBeArray,将整数数值0x00000001转换成[00,00,00,01]字符数组,然后经通信接口发给芯片;2、芯片接收到4字节数据之后,通过函数ConverseArrayToLeUI,将[01,00,00,00]转换成整数0x00000001。

  4、使用总结

  (1)不同的硬件平台如果采用同一种类型的端序,计算/使用时无需转序;

  (2)不同的硬件平台如果采用不同类型的的端序,但传输的字符数组“无需”转换成多字节基本类型数据(如int,double,float)时,计算/使用时无需转序;

  (3)不同的硬件平台如果采用不同类型的的端序,但传输的字符数组“需要”转换成多字节基本类型数据(如int,double,float)时,计算/使用时需要转序;

时间: 2024-08-01 12:15:38

大小端序转换的相关文章

[C/C++]_[初级]_[判断大小端序Little Endian Order]

场景: 1. 在读取硬盘数据和媒体数据时,需要根据读取的数据进行大小端序的转换,以正确识别数据.其中一个处理就是首先要判断cpu支持的大小端序情况才能转换. 2. Little Endian Order: 低地址存低位(整数的高低位)的数据. test.cpp #include <stdio.h> #include <iostream> using namespace std; //1.方法1,通过判断int的低位是否存储了数值. int IsLittleEndian1() { i

【转】htonl(),htons(),ntohl(),ntons()--大小端模式转换函数

转自 http://www.cnblogs.com/kungfupanda/archive/2013/04/24/3040785.html 不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian).大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处.小端模式是指低字节数据存放在低地址处,高字节数据放在高地址处. 在网络上传输数据时,由于数据传输的两端可能对应不同的硬件平台,采用的存储字节顺序也可能不一致,因此 TCP

java的大小端和转换

一直以为大小端针对的bit的顺序,今天才知道:大小端的分度值是 byte,即每一个byte都是按照正常顺序,但是byte组装成一个int 或者是 long等时每个byte的摆放位置不同. 测试代码: public class BufferTest { @Test public static void main(String[] args) { ByteBuffer buffer= ByteBuffer.allocate(4); buffer.order(ByteOrder.BIG_ENDIAN)

判断大小端序的C程序

概念 大端格式:字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中. 小端格式:与大端存储格式相反,在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节. 如5A6C中5A是高字节.6C是低字节,在大端序机器中,高字节位于低地址中,即在大端序中按照5A6C存储,在小端序中按照6C5A存储. 为什么存在这种模式 因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit.但是在C语言中除了8bit的char之外,还有16bit的

大小端模式转换函数

#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); htonl 表示 host to network long ,用于将主机 unsigned int 型数据转换成网络字节顺序: htons 表示 host to netwo

写一程序,判断运行程序的系统是大字节序还是小字节序?写函数实现大小字节序转换

#include <stdio.h> #include <netinet/in.h> int main() { int i_num = 0x12345678; printf("[0]:0x%x\n", *((char *)&i_num + 0)); printf("[1]:0x%x\n", *((char *)&i_num + 1)); printf("[2]:0x%x\n", *((char *)&

C# Socket流数据大小端读写封装

网络数据是大端模式,而c#中的数据小端结构,那么在读写网络数据的时候需要进行转换.c#类库IPAddress已经封装了大小端的转换. 封装代码如下: [csharp] view plain copy using System.IO; using System.Net; using System; namespace Framework { public class NetStream { private MemoryStream stream; private BinaryReader read

【转】[c/c++ ]字节序与大小端转换--不错

原文网址:http://blog.csdn.net/kuai0705/article/details/20841133 注明: 以下内容均为学习内容整理,记录,便于自己学习,并非完全意义上的自产,如有感到不适,请联系我 一.多字节值及字节序 1.brief 现在有一个数字 65430,这个数字在二进制的内存中一个字节无法完全存下,存储这个数字需要1个字节以上的空间.这样的值被称为多字节量(multi-byte quantity). 65430在内存中由两个字节表示:0xFF 和 0x96 ,其中

关于大小端问题和字节序问题的一些总结

1.大小端是不同的对于数据在内存地址中的存放方式,不同的处理器(平台)的数据存储方式是不同.的如果 实现跨平台通信则大小端是不能忽视的问题. 大端模式:数据的高位存储在内存的低字节.ARM/PowerPC等处理器采用大端模式 小端模式:数据的地位存储在内存的低字节.Intel架构处理器采用小端模式. 如一个数据:0x12345678;对应内纯地址是0x00~0x03. 大端模式: 小端模式: 地址:0x00 0x01 0x02 0x03 地址:0x00 0x01 0x02 0x03 数据:0x1