zoukankan      html  css  js  c++  java
  • struct和union的用法

    1.结构体类型

         数组、结构体(struct)类型、共用体(union)类型、枚举(enumeration)类型这些类型统称用户自定义类型(user-defined type,UDT),本次介绍结构体类型。

    1.1声明结构体类型

          在C语言中允许用户自己指定一个组合项,在一个组合项中包含若干类型的数据项,这种数据类型称为结构体。
    形如:
    struct student_tag 
    {
    	int num;		//包括一个int变量
    	char name[20];	//包括一个字符数组
    	char sex;		//包括一个字符
    	int age;		//包括一个int变量
    	float score;	//包括一个float变量
    	char addr[30];	//包括一个字符数组
    };					//最后有一个分号

           struct student_tag就是用户自己指定的新的结构体类型名,该类型包括num、name、sex等成员;其中struct是声明结构体类型时所使用的关键字,它向编译系统声明这是一个“结构体类型”。它在内存中的结构如下:

                                              图 1  struct变量内存分布

    结构体变量占用的内存大小是各成员占的内存长度之和,每个成员分别占有其自己的内存单元(不考虑边界等情况),struct student_tag 变量的大小是:4+20+1+4+4+30 = 63.
    声明结构体类型的一般形式:

    struct 结构体标记

    {

       成员列表

    };

    1.2定义结构体变量

         指定了一个结构体类型,它相当于一个模型,其中并无具体的数据,系统也不分配实际的内存单元。它和系统提供的标准类型(如int)具有相同的作用,可以用来定义变量;为了能在程序中使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放数据。

    例如:

    struct student_tag stu1,stu2;//stu1,stu2是结构体变量名

           应当注意,定义结构体变量时要指定为某一特定的结构体类型(如struct student_tag、struct map_tag类型),因为用户可以定义出许许多多种具体的结构体类型。

    1.3引用结构体变量

    在定义了结构体变量以后,当然可以引用这个变量。

    (1)具有相同类型的结构体变量可以实现整体赋值;

    stu1 = stu2;
    在赋值时,stu2中的成员是分别赋值给stu1的相应的成员;

    (2)引用结构体变量中的一个成员值,引用结构体变量中成员的一般形式:

    结构体类型名.成员名(“.”成员运算符)

    stu1.num = 41008;
    (3)如果成员本身也是一个结构体类型,则要用若干个成员运算符,一级一级找到最低一级的成员。
    struct date_tag
    {
       int month;
       int day;
    };
    
    struct student_tag 
    {
        int num;		         //包括一个int变量
    
        struct date_tag birthday;//struct date_tag结构体变量
    };					
    
     ...
    student_tag stu3;
    
    stu3.birthday.month = 10;
    (4)不能将结构体变量作为整体进行输入和输出
    printf("%d...",stu3);//error

    2.共用体

    2.1共用体的概念

         共用体是一种构造类型的数据结构。在一个“共用体”内可以定义多种不同的数据类型,这些变量共享同一段内存,已达到节省空间的目的,共用体内的变量互相覆盖。

    定义共用体类型变量的一般形式

    union 共用体名

    {

    成员表列;

    }变量表列;

    例如:

    union data
    {
    	int i;
    	char ch;
    	float f;
    }a,b;

    可以看见,“共用体”与“结构体”的定义形式相似,但他们的含义不同。共用体的各成员变量在内存中的字节数可能不同,但这些变量都放在从同一个地址开始的内存单元中,共用体变量所占的内存长度最长的成员长度。变量在内存中的情况如下:

                                                                                        图 2 union变量内存分布

    2.2共用体类型数据的特点

    (1)同一个内存段内可以用来存放几种不同的数据类型,但是每一瞬时只能存放其中的一个数据,即每一个瞬时只有一个成员起作用,其他的成员不起作用。

    (2)共用体变量中起作用的是最后一次存放的成员,每次只能赋一种值, 赋入新值则冲去旧值。

    例如:

    b.ch = 'a';  
    b.i = 0x00004241;
    
    printf("%c",b.ch);//结果:A

    (3)共用体变量的地址和它的各成员的地址是同一个地址;

    (4)共享内存从union的首地址开始放置,从最低地址开始覆盖

    3.加深struct和union的理解

    在此之前先简单介绍计算机中的两个术语:

    大端模式,是指数据的高位保存在内存的低地址中,而数据的低位保存在内存的高地址中。

    小端模式,是指数据的高位保存在内存的高地址中,而数据的低位保存在内存的低地址中。

    在一般情况下x86结构是小端模式,本机就是如此!

    int data = 0x00004241;

    在内存中它们存储的方式有两种:


                                    图 3  大端模式 


                           图 4  小端模式

    看如下的代码:

    union number           /*定义一个联合*/
    	{                     
    		int i;
    		struct
    		{                  
    			char first;
    			char second;
    		}half;             /*在联合中定义一个结构*/
    	}num;
    
    	num.i=0x00004241;      /*联合成员赋值*/
    	printf("%c%c
    ", num.half.first, num.half.second);
    
    	num.half.first='a';    /*联合中结构成员赋值*/
    	num.half.second='b';
    	printf("%x
    ", num.i);
    输出结果:

    AB

    6261

    分析与内存变化:

    num.i = 0x00004241对应step1,num.half.first = 'a' num.half.second= 'b'对应step2,printf("%x ",num.i)对应step3;由于在我的机器中是小端模式,故四字节的“61620000”代表的十六进制整数是“6261”。

    图 5 内存变化过程

    4.union中存放的数据类型

    1.联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存

    2.联合里不允许存放带有构造函数、析够函数、复制拷贝操作符等的类,因为他们共享内存,编译器无法保证这些对象不被破坏,也无法保证离开时调用析够函数。

    5.共享内存特性的几种应用

    union data
    {
    int i;
    unsigned char c[4];
    float f;
    };
    union data a;//定义union类型的变量

    1.在需要将浮点数据转移时,使用共同体,按4个字节的char型数据传输,带来通信效率的提高。

    一般浮点数发送方法:是将浮点数放大一定的倍数,再取整,再按整数的高低位传输。还需要传输这个放大的倍数,如果浮点数是个负数的话,还要将符号一并发送。接收方收到这几条报文后,才能将数据还原。但是接收方还原的浮点数据与发送方发送的浮点数不一样,因为小数位数发生变化。使用共同体就不会出现这个问题了,在接收方,使用共同体,将收到到的4个char数据赋值给a.c数组,a.f就是还原的数据,这个数据和发送的数据是一样的,也不管发送的浮点数是正还是负。如有a.f = -12.34; 则a.c[0] = 0xa4, a.c[1] = 0x70, a.c[2] = 0x45, a.c[3] = 0xc1。如有a.c[0] = 0xa4, a.c[1] = 0x70, a.c[2]= 0x45, a.c[3] = 0xc1,则a.f =-12.34。使用这种方式传输浮点数,数据是不会丢失的,报文也更简单。

    2.将浮点数保存到文件中时,保存为4个字节的char型数据,节约空间。如果保存为文本需要占用的字节数等于数值的字符的个数,有可能占用1~20字节,而用共用   体的char型数据,占用的空间大小固定为4字节,对大量浮点数据的存储,节约的空间更多,分析保存的浮点数也是很方便的。

    3.用在强制类型转换上。如将int数据转为float,可以这样使用union: a.i =1234;赋值后,a.f就是转换后的值等于1234。

    4.当多种类型,多个对象,多个事物只取其一时(称其为n选一)我们可以使用联合体来发挥其长处。


  • 相关阅读:
    在Leangoo里怎么添加,移动列表,修改列表名称?
    在Leangoo里怎么列表示例,插入列表?
    tomcat如何按站点调试本机程序
    ORA-12519, TNS:no appropriate service handler found
    mysql 远程访问
    手机端调试成功笔记
    Cannot find class for bean with name service
    android模拟器不能用键盘
    eclipse使用基础--让toolbar显示自己想要的内容
    mysql解压版安装
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468448.html
Copyright © 2011-2022 走看看