• 泥淖--------------------大小端


    声明:文章仅为个人总结所用,鄙人菜鸟,高手勿喷,欢迎批评指正。

    经常看到通过联合体Union来判断系统是大端还是小端,而大家的解释通常都是:“联合体union的存放顺序是所有成员都从低地址开始存放,解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。”而我却始终没有找到这句话是出自哪本书。

    我知道unsigned short a = 0x1122在大端中存的话就是0x1122,而如果是在小端CPU上运行的话就是0x2211。疑问:

    1. 那么如果取a的低八位即a&0xff的话,是不是在大端中是0x22,而在小端中就是0x11呢?

    2. 那么如果a向右移位即a>>8取得其高八位的话,是不是再大端中是0x11,而在小端中就是0x22呢?

    3. 那么如果将a赋值给unsigned char b,即b = (unsigned char)a,考虑到类型强转,取short型低八位赋值给char型,那么short型的低八位是多少呢?在大端中存的话,低八位是0x22,而在小端中存的话是0x11,那么是不是在不同架构的CPU上,结构就不相同呢?

    4. 为什么通过联合体可以判断是大端还是小端?除了那个找不到出处的解释外,还有其他的解释吗?

    5. 除了网上盛传的两种判断大小端的方法外,还有其他判断大小端的方法吗?


    还是先列出网上盛传的其中一种判断方法吧:

    void JudgeEndianByInt()
    {
        unsigned short temp = 0x1122;
    
        if(((char *)&temp)[0] == 0x11)
        {
            printf(_BIG_ENDIAN_);
        }
        else
        {
            printf(_Little_ENDIAN_);
        }
    }

    我对这个函数的理解:直接根据大小端的定义来判断,如果该数据的低地址为存放的是该数据的低数据位,那么就是小端,否则就是大端。当然我也可以理解为,将指向short型数据的指针强制转换为char型指针,那么就要取其低地址赋值给char型指针,因此如果该低地址存放的是数据的低位,那么就是小端。

    另外一种方法:

    typedef union
    {
        int val_1;
        char val_2;
    }Union_Test;
    
    void JudgeEndianByUnion()
    {
        Union_Test u;
    
        u.val_1 = 0x11;
    
        if(u.val_2 == 0x11)
        {
            printf(_Little_ENDIAN_);
        }
        else
        {
            printf(_BIG_ENDIAN_);
        }
    
    }

    我对这个函数的理解:其实这个判断和第一个判断原理是一样的,都是将同一个short型的内存区的值强制转换成char型的内存区,那么就要取其低位,如果地位存储的是低数据位,则是小端。

    然后我来分析我的那么些个疑问。

    1 2 ,位操作是针对二进制位的,是针对数据的二进制位的,不关乎内存地址的东西,所以不同平台不会有影响。

    3. 也不会,强转的是数据的值,不是数据的地址,不会变化。

    4. 有很多,只有能获得地址的方法或者根据地址进行判断的都是可行的,比如:

    void JudgeEndianByMemory()
    {
        unsigned short temp = 0x11;
        unsigned char temp_2 = 0;
    
        memcpy(&temp_2,&temp,sizeof(temp_2));
    
        if(temp_2 == 0x11)
        {
            printf(_Little_ENDIAN_);
        }
        else
        {
            printf(_BIG_ENDIAN_);
        }
    }

    或者调用系统函数htonl ntohl等:

    void HostToNet(ElemType val)
    {
    	printf("val is 0x%x  htonl(val) is 0x%x  htonl(htonl(val))  0x%x
    ",val,htonl(val),htonl(htonl(val)));
    }
    
    void NetToHost(ElemType val)
    {
    	printf("val is 0x%x  ntohl(val) is 0x%x  ntohl(ntohl(val))  0x%x
    ",val,ntohl(val),ntohl(ntohl(val)));
    }
    

      因时间关系,今天暂时到此为止。

    欢迎大家跟帖讨论,如有纰漏,欢迎指正,谢谢~

  • 相关阅读:
    js 字符串indexOf方法封装
    js 冒泡排序
    CSS定位 position的三个属性 elative 、absolute、fixed :
    让父元素能感知浮动的子元素 #用伪元素清除浮动
    三个路由器的连接,中间路由的配置(静态路由)
    IDEA 添加tomcat出错: Error: Environment variable name is not set 我的解决方法
    通过基于AspectJ 注解的方式实现Spring AOP报 can't find referenced pointcut myPointCut 错误,我的解决方法
    C语言fopen函数打开文本文件与二进制文件的区别
    位运算的奇技淫巧 系列1
    位运算例子(以后会逐渐补充)
  • 原文地址:https://www.cnblogs.com/xiaowenhu/p/3233232.html
Copyright © 2020-2023  润新知