• 【简单介绍+实践】大端、小端、主机序、网络序


    一、概念

        小端即主机序,即内存的低地址段先存数据的低位,然后在存高位,有种由小到大存储的感觉,所以称为小端。

        大端即网络序,即内存的低地址段先存数据的高位,然后在存低位,有种由小到大存储的感觉,所以称为大端。

        我们最常见的X86 CPU采用的是小端,所以小端又称主机序。其实还有一些其他CPU也是大端的,但本人接触较少,不做说明了。

        网络传输协议中都采用大端,so大端又称网络序。

    二、小端环境中打印存储地址的示例

    #include<stdio.h>
    
    #define BYTE    unsigned char
    #define WORD32  unsigned int
    
    int main(void)
    {
        BYTE* pb = 0;
        WORD32 i = 0x12345678;
        WORD32 j;      
        
        pb = (BYTE*)&i;
        
        for(j = 0; j < (sizeof(WORD32)/sizeof(BYTE)); j++)
        {
            printf("(pb+%u) value = %X \t", j,*(pb+j));    
            printf("address = %X \n", (pb+j));        
        }
        
        return 0;
    }

        在X86+linux环境下测试,输出结果为:

    (pb+0) value = 78       address = BFFFF410
    (pb+1) value = 56       address = BFFFF411
    (pb+2) value = 34       address = BFFFF412
    (pb+3) value = 12       address = BFFFF413

    三、大小端数据互转的示例

    #include<stdio.h>
    
    #define BYTE    unsigned char
    #define WORD16  unsigned short
    #define WORD32  unsigned int
    
    #define s_endian_swap(x)            \
        ( ((((x)&0x00ff)<<8)&0xff00) |  \
          ((((x)&0xff00)>>8)&0x00ff)    )
    
    #define l_endian_swap(x)            \
        ( ((((x)&0x000000ff)<<24)&0xff000000) |  \
          ((((x)&0x0000ff00)<<8) &0x00ff0000) |  \
          ((((x)&0x00ff0000)>>8) &0x0000ff00) |  \
          ((((x)&0xff000000)>>24)&0x000000ff) )
    
    #ifndef ntohs
    #define ntohs(x)        s_endian_swap(x)
    #endif
    
    #ifndef ntohl
    #define ntohl(x)        l_endian_swap(x)
    #endif
    
    int main(void)
    {
        BYTE    abData[4];
        BYTE*   pb = 0; 
        WORD32  j;      
        WORD16  wOutput;
        WORD32  dwOutput;
        
        /* 模拟一下网络序(大端)中数据0x12345678的存储状态 */
        abData[0]  = 0x12;
        abData[1]  = 0x34;
        abData[2]  = 0x56;
        abData[3]  = 0x78;
        
        pb         = abData;
        
        /* 不放心可以打印确认一下 */
        for(j = 0; j < (sizeof(WORD32)/sizeof(BYTE)); j++)
        {
            printf("(pb+%u) value = %X \t", j,*(pb+j));    
            printf("address = %X \n", (pb+j));        
        }    
        
        /* 这时候直接通过强转取值就会出错 */
        wOutput  = *(WORD16*)pb;
        dwOutput = *(WORD32*)pb;
        
        /* 看看都错了吧。可以想想为什么是这两个错误值? */
        printf("the wrong wOutput  = 0x%x \n",    wOutput);      /* 输出为0x3412     */
        printf("the wrong dwOutput = 0x%x \n",    dwOutput);     /* 输出为0x78563412 */
        
        /* 字节序转换宏来拯救世界了  */
        wOutput  = ntohs(wOutput);
        dwOutput = ntohl(dwOutput);
        
        /* 这下都对了吧 */
        printf("the right wOutput  = 0x%x \n",    wOutput);      /* 输出为0x1234     */
        printf("the right dwOutput = 0x%x \n",    dwOutput);     /* 输出为0x12345678 */
    
        return 0;
    }
  • 相关阅读:
    Mac安装WineHQ
    Ubuntu 16.04下使用Wine安装文件比对工具Beyond Compare 4
    Ubuntu 16.04下安装WineHQ
    Ubuntu 16.04下使用Wine安装PowerDesigner15
    Ubuntu 16.04下使用Wine安装Windows版的微信(不太完美)
    Ubuntu 16.04下使用Wine安装Xshell 4和Xftp 4
    MySQL中数据类型(char(n)、varchar(n)、nchar(n)、nvarchar(n)的区别)(转)
    Ubuntu 16.04安装MongoDB的GUI工具RoboMongo
    Linux下Shell的快捷键(转)
    Jackson反序列化错误:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field的解决方法
  • 原文地址:https://www.cnblogs.com/joyer/p/3027381.html
Copyright © 2020-2023  润新知