zoukankan      html  css  js  c++  java
  • [C/C++]大小端字节序转换程序

    计算机数据存储有两种字节优先顺序:高位字节优先(称为大端模式)和低位字节优先(称为小端模式)。

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

    例子:对于内存中存放的数0x12345678来说
    如果是采用大端模式存放的,则其真实的数是:0x12345678
    如果是采用小端模式存放的,则其真实的数是:0x78563412

    如果称某个系统所采用的字节序为主机字节序,则它可能是小端模式的,也可能是大端模式的。
    而端口号和IP地址都是以网络字节序存储的,不是主机字节序,网络字节序都是大端模式。
    要把主机字节序和网络字节序相互对应起来,需要对这两个字节存储优先顺序进行相互转化。
    这里用到四个函数:htons(),ntohs(),htonl()和ntohl().
    这四个地址分别实现网络字节序和主机字节序的转化,这里的h代表host,n代表network,s代表short,l代表long。
    通常16位的IP端口号用s代表,而IP地址用l来代表。

    #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 network short ,用于将主机 unsigned short 型数据转换成网络字节顺序;
    ntohl、ntohs 的功能分别与 htonl、htons 相反。

     

    如图,i为int类型占4个字节,但只有1个字节的值为1,另外3个字节值为0;取出低地址上的值,当其为1时则为小端模式,为0时为大端模式。

    //大小端模式的判断
    //方法一:利用联合体所有成员的起始位置一致,
    //对联合体中的int类型赋值,然后判断联合体中char类型的值的大小
    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    //signed
    typedef signed char        int8;
    typedef short              int16;
    typedef int                int32;
    typedef long long          int64;
    //unsigned
    typedef unsigned char      uint8;
    typedef unsigned short     uint16;
    typedef unsigned int       uint32;
    typedef unsigned long long uint64;
    
    #pragma pack(push)
    #pragma pack(1)//单字节对齐
    typedef struct{
        uint32 ID;
        uint32 Num;
        uint32 Type;
        uint32 lat;
        uint32 lng;
        uint32 alt;
        uint32 speed;
    }Waypoint;//Payload_Data
    
    #pragma pack(pop)
    
    
    
    
    void EndianSwap(uint8 *pData, int startIndex, int length);
    
    
    
    int main()
    {
    
        Waypoint wp,wp_ori;
        int len = sizeof(Waypoint);
        cout << "size of Waypoint: " << len << endl;
    
        wp.ID    = 0x00000011;
        wp.Num   = 0x00002200;
        wp.Type  = 0xDD0CB0AA;
        wp.lat   = 0x00330000;
        wp.lng   = 0x44000000;
        wp.alt   = 0xABCD1234;
        wp.speed = 0x12345678;
    
        wp_ori = wp;
    
    
        int i = 0;
        uint8* pData = (uint8*)(&wp);
        for (i = 0; i < len; i += 4)
        {
            EndianSwap(pData,i,4);
        }
    
    
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.ID << endl;
        cout << uppercase << hex << "改变字节序后: 0x" <<setfill('0') << setw(8) << wp.ID <<endl;
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.Num << endl;
        cout << uppercase << hex << "改变字节序后: 0x" << setfill('0') << setw(8) << wp.Num << endl;
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.Type << endl;
        cout << uppercase << hex << "改变字节序后: 0x" << setfill('0') << setw(8) << wp.Type << endl;
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.lat << endl;
        cout << uppercase << hex << "改变字节序后: 0x" << setfill('0') << setw(8) << wp.lat << endl;
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.lng << endl;
        cout << uppercase << hex << "改变字节序后: 0x" << setfill('0') << setw(8) << wp.lng << endl;
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.alt << endl;
        cout << uppercase << hex << "改变字节序后: 0x" << setfill('0') << setw(8) << wp.alt << endl;
        cout << endl;
        cout << uppercase << hex << "改变字节序前: 0x" << setfill('0') << setw(8) << wp_ori.speed << endl;
        cout << uppercase << hex << "改变字节序后: 0x" << setfill('0') << setw(8) << wp.speed << endl;
        return 0;
    }
    
    void EndianSwap(uint8 *pData, int startIndex, int length)
    {
        int i,cnt,end,start;
        cnt = length / 2;
        start = startIndex;
        end  = startIndex + length - 1;
        uint8 tmp;
        for (i = 0; i < cnt; i++)
        {
            tmp            = pData[start+i];
            pData[start+i] = pData[end-i];
            pData[end-i]   = tmp;
        }
    }
    
    

      运行结果如下:

  • 相关阅读:
    解析空白符(空白,制表)分隔的字串
    关于select—页面中的ListBox的Javascript
    【函数】strcat源代码
    【SQL语法】系列08:利用Update更新表中数据
    【函数】fill和fill_n填充之区别
    【Xcode】编辑与调试
    【网站】在WAMP下安装wordpress
    【SQL语法】系列06:利用ORDER BY排序
    【SQL语法】系列07:利用insert into插入新行
    【Boost】系列03:内存管理之shared_ptr智能指针
  • 原文地址:https://www.cnblogs.com/wuyepeng/p/9833273.html
Copyright © 2011-2022 走看看