联合体union用在何处?

  程序设计初学者在学习时,总想问:“这个东东有什么用?”于是,在建设有关的教学资源时,也便总从这个角度,试图给出一些案例,这是一个将初学者作为教学目标人群的人该干的事。
  然而,在准备这样一些案例时,诸如循环、数组、结构体之类的,可以编出一堆堆的能体现实际应用的案例,或出例题,或出实践题目,都好说。然而,对于有些在教科书中的“小知识点”,作为讲程序设计语言,有些老师都选择不讲的,能却总是不易编出。
  主要的原因,是这些内容要解决的问题,似乎并不常见。针对特殊的应用场合,不知道初学者是否能耐着性子将应用背景搞明白。而不少能真正应用的场合,还涉及到一些基础的知识。
  例如枚举。如果读一些工程级应用的源码,到处要用。而遍找各路资料,也就是那几个例子,目的是讲清语法。要有应用味,还要尽可能简单,编出的示例中,有两个还算满意,一个是老贺买车(见链接中例程,来源于真实故事),另一个是键盘输入的检测(见链接中项目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;
时间: 2025-01-26 15:25:21

联合体union用在何处?的相关文章

C++联合体union用法实例详解

  本文实例讲述了C++联合体union用法.分享给大家供大家参考.具体如下: 我们应该按照C中的convention去使用union,这是我这篇文章要给出的观点.虽然C++使得我们可以扩展一些新的东西进去,但是,我建议你不要那样去做,看完这篇文章之后,我想你大概也是这么想的. C由于没有类的概念,所有类型其实都可以看作是基本类型的组合,因此在union中包含struct也就是一件很自然的事情了,到了C++之后,既然普遍认为C++中的struct与class基本等价,那么union中是否可以有类

结构体struct、枚举enum、联合体union、位字段、自定义类型typedef、字节对齐

结构体struct 1 结构体的基本知识 2 结构体与函数 3 结构体数组 4 自引用结构体 枚举变量enum 联合体union 位字段 1 一般的方法定义屏蔽吗 2 用位字段来定义屏蔽吗 自定义类型typedef 字节对齐 pragma pachx 按x个字节对齐 1.结构体struct 1.1 结构体的基本知识 #include <stdio.h> struct point{ int x; int y; }p1, p2, p3; struct point pt; struct point

C++联合体union用法实例详解_C 语言

本文实例讲述了C++联合体union用法.分享给大家供大家参考.具体如下: 我们应该按照C中的convention去使用union,这是我这篇文章要给出的观点.虽然C++使得我们可以扩展一些新的东西进去,但是,我建议你不要那样去做,看完这篇文章之后,我想你大概也是这么想的. C由于没有类的概念,所有类型其实都可以看作是基本类型的组合,因此在union中包含struct也就是一件很自然的事情了,到了C++之后,既然普遍认为C++中的struct与class基本等价,那么union中是否可以有类成员

C语言编程中的联合体union入门学习教程_C 语言

联合体(union)在C语言中是一个特殊的数据类型,能够存储不同类型的数据在同一个内存位置.可以定义一个联合体使用许多成员,但只有一个部件可以包含在任何时候给定的值.联合体会提供使用相同的存储器位置供多用途的有效方式. 定义联合体要定义联合体,必须使用union语句很相似于定义结构.联合体声明中定义了一个新的数据类型,程序不止一个成员.联合体声明的格式如下: union [union tag] { member definition; member definition; ... member

Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型

Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面也讲了许多,也提到了多级指针的概念,那具体我们怎么去操作呢 #include <stdio.h> #include <stdlib.h> main(){ int i = 3; //一级 int* p = &i; //二级,保存一级指针 int** w = &p; //三

《奔跑吧Linux内核》之处理器体系结构

本文摘自人民邮电出版社异步社区<奔跑吧Linux内核> 第1章 处理器体系结构 京东购书:https://item.jd.com/12152745.html 试读地址:http://www.epubit.com.cn/book/details/4835本章思考题 1.请简述精简指令集RISC和复杂指令集CISC的区别. 2.请简述数值0x12345678在大小端字节序处理器的存储器中的存储方式. 3.请简述在你所熟悉的处理器(比如双核Cortex-A9)中一条存储读写指令的执行全过程. 4.请

大端和小端(Big endian and Little endian)

一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放据的低位字节到高位字节). 例如,假设从内存地址 0x0000 开始有以下数据:   0x0000         0x0001       0x0002       0x0003   0x12            0x34        

iOS面试题总结 一

1.写一个NSString类的实现 + (id)initWithCString:(c*****t char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;  + (id) stringWithCString: (c*****t char*)nullTerminatedCString               encoding: (NSStringEncoding)encoding  {    NSString  *obj

一道用 sizeof 求结构体所占大小的笔试题?求教

问题描述 一道用 sizeof 求结构体所占大小的笔试题?求教 下列程序,为什么输出的结果是 120? int main(int argc, char* argv[]) { union u_type { int i; double x; float f; }; struct str_type { char str[100]; union u_type u[2]; }; printf("%dn",sizeof(struct str_type)); } 解决方案 首先union u_typ