zoukankan      html  css  js  c++  java
  • 联合体union用在何处?

      程序设计刚開始学习的人在学习时,总想问:“这个东东有什么用?”于是,在建设有关的教学资源时,也便总从这个角度,试图给出一些案例,这是一个将刚開始学习的人作为教学目标人群的人该干的事。
      然而,在准备这样一些案例时,诸如循环、数组、结构体之类的,能够编出一堆堆的能体现实际应用的案例。或出例题,或出实践题目,都好说。然而,对于有些在教科书中的“小知识点”。作为讲程序设计语言,有些老师都选择不讲的,能却总是不易编出。
      基本的原因,是这些内容要解决的问题,似乎并不常见。

    针对特殊的应用场合。不知道刚開始学习的人能否耐着性子将应用背景搞明确。而不少能真正应用的场合,还涉及到一些基础的知识。


      比如枚举。

    假设读一些project级应用的源码。到处要用。而遍找各路资料,也就是那几个样例。目的是讲清语法。

    要有应用味,还要尽可能简单。编出的演示样例中,有两个还算惬意,一个是老贺买车(见链接中例程,来源于真实故事),还有一个是键盘输入的检測(见链接中项目2,中间关于键盘值还不能给学习者展开。)
      再如。本文要说的联合体。讲义中贡献出了自编还算惬意的IP地址(见链接中。以前扩展过的利用子网掩码检測是否同一网段的部分省略了),再找到惬意些的的资料和想到的内容,主要在于和计算机底层相关的应用。对于刚開始学习的人。恐怕等一等更好。
      对于我的工作,继续花时间建设让刚開始学习的人在有限积累前提下就能“提前体验”的方法和资源,而也寄语刚開始学习的人,不少有大用的知识,限于学习者学习的阶段性,继续前行你才干知道。

    在这个阶段。别人想给你讲清,并不现实。人说这是个浮躁的时代。静心读书,不惜尚不知其用也要学下去,这能够是一种选择。

      一番感慨之后,还是给出为主题“联合体union用在何处”要给出的案例。以下的内容部分转载自点击打开…。积累下去。应用场合绝不止这些
      

    试题一

      编写一段程序推断系统中的CPU 是Little endian 还是Big endian 模式?
    分析:
      作为一个计算机相关专业的人,我们应该在计算机组成中都学习过什么叫Little endian 和Big endian。

    Little endian 和Big endian 是CPU 存放数据的两种不同顺序。对于整型、长整型等数据类型,Big endian 觉得第一个字节是最高位字节(依照从低地址到高地址的顺序存放数据的高位字节到低位字节);而Little endian 则相反,它觉得第一个字节是最低位字节(依照从低地址到高地址的顺序存放数据的低位字节到高位字节)。


      比如,假设从内存地址0x0000 開始有以下数据:

    0x12 0x34 0xab 0xcd

      假设我们去读取一个地址为0x0000 的四个字节变量,若字节序为big-endian。则读出结果为0x1234abcd;若字节序位little-endian,则读出结果为0xcdab3412。假设我们将0x1234abcd 写入到以0x0000 開始的内存中。则Little endian 和Big endian 模式的存放结果例如以下:

    地址 0x0000 0x0001 0x0002 0x0003
    big-endian 0x12 0x34 0xab 0xcd
    little-endian 0xcd 0xab 0x34 0x12

      一般来说,x86 系列CPU 都是little-endian 的字节序,PowerPC 一般是Big endian,还有的CPU 能通过跳线来设置CPU 工作于Little endian 还是Big endian 模式。
    解答:
      显然,解答这个问题的方法仅仅能是将一个字节(CHAR/BYTE 类型)的数据和一个整型数据存放于相同的内存始地址,通过读取整型数据。分析CHAR/BYTE 数据在整型数据的高位还是低位来推断CPU 工作于Little endian 还是Big endian 模式。
      得出例如以下的答案:

    typedef unsigned char BYTE;
    int main(int argc, char* argv[])
    {
        unsigned int num,*p;
        p = #
        num = 0;
        *(BYTE *)p = 0xff;
        if(num == 0xff)
        {
            printf("The endian of cpu is little/n");
        }
        else //num == 0xff000000
        {
            printf("The endian of cpu is big/n");
        }
        return 0;
    }

      除了上述方法(通过指针类型强制转换并对整型数据首字节赋值,推断该赋值赋给了高位还是低位)外,还有没有更好的办法呢?我们知道,union 的成员本身就被存放在相同的内存空间(共享内存,正是union 发挥作用、做贡献的去处),因此。我们能够将一个CHAR/BYTE 数据和一个整型数据同一时候作为一个union 的成员,得出例如以下答案:

    int checkCPU()
    {
        {
            union w
            {
                int a;
                char b;
            } c;
            c.a = 1;
            return (c.b == 1);
        }
    }

      实现相同的功能,我们来看看Linux 操作系统中相关的源码是怎么做的:

    static union { char c[4]; unsigned long mylong; } endian_test = {{ 'l', '?', '?', 'b' } };
    #define ENDIANNESS ((char)endian_test.mylong)

      Linux 的内核作者们仅仅用一个union 变量和一个简单的宏定义就实现了一大段代码相同的功能。由以上一段代码我们能够深刻领会到Linux 源码的精妙之处!

    (假设ENDIANNESS=’l’表示系统为little endian,为’b’表示big endian )

    试题二

      假设网络节点A 和网络节点B 中的通信协议涉及四类报文。报文格式为“报文类型字段+报文内容的结构体”,四个报文内容的结构体类型分别为STRUCTTYPE1~ STRUCTTYPE4,请编敲代码以最简单的方式组织一个统一的报文数据结构。
    分析:
      报文的格式为“报文类型+报文内容的结构体”。在真实的通信中,每次仅仅能发四类报文中的一种,我们能够将四类报文的结构体组织为一个union(共享一段内存,但每次有效的仅仅是一种),然后和报文类型字段统一组织成一个报文数据结构。


    解答:
      依据上述分析,我们非常自然地得出例如以下答案:

    typedef unsigned char BYTE;
    //报文内容联合体
    typedef union tagPacketContent
    {
        STRUCTTYPE1 pkt1;
        STRUCTTYPE2 pkt2;
        STRUCTTYPE3 pkt1;
        STRUCTTYPE4 pkt2;
    } PacketContent;
    //统一的报文数据结构
    typedef struct tagPacket
    {
        BYTE pktType;
        PacketContent pktContent;
    } Packet;
  • 相关阅读:
    java工具类4-分布式id生成器
    java工具类3-签名加密
    java工具类2-获取文件base64
    Java SE入门(十)——继承与抽象
    Java SE入门(九)——静态和代码块
    Java SE入门(八)——IO流基础
    Java SE入门(七)——Java集合与实例
    Java SE入门(六)——常用基础API
    Java SE入门(五)——面向对象基础
    Java SE入门(四)——函数与方法
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6978663.html
Copyright © 2011-2022 走看看