C语言学习第十五天(共用体、枚举)

本文详细介绍了C语言中的共用体(union)和枚举(enum)的概念及应用。共用体允许不同类型的数据共享同一段内存,而枚举则用于定义有限个数的整型常量集合。文章通过实例展示了如何定义和使用这些特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。


共用体定义:

union 共用体名

{

   成员表名

}变量表名

例:

/*先声明类型再定义*/
union student
{
    int num;
    char name;
    float score;
}xiaowang;
    
/*直接定义*/
union
{
    int num;
    char name;
    float score;
}xiaowang;

结构体变量所占内存长度是各成员占的内存长度之和,每个成员分别占有其自己的内存单元。

公用体变量所占内存长度是等于最长的成员长度。

上面的例子所占长度是各占4个字节 (实型变量占4个字节)而不是2+1+4=7个字节

一些书中把公用体也叫 -> "联合"


注意特点:

1.同一内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是其中几种。

2.共用体变量起作用的成员是最后一次存放的成员,再存入一个新的成员后,原有成员失去作用,如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union
{
    int num;
    char name[20];
    float score;
}xiaowang;
    
    
main()
{
    xiaowang.num=1;
    strcpy(xiaowang.name,"xiaowang");
    xiaowang.score = 88;
    printf("%d",xiaowang.num);
    /*此时xiaowang.num已经失去了意义*/
}


3.共用体变量的地址和各成员变量的地址都是同一地址

4.不能用共用体变量名赋值,也不能引用变量名来得到一个值,又不能在定义共用体变量时对它初始化

5.不能把共用体变量作为参数,也不能使函数返回时带有共用体,但可以使用指向共用体变量的指针(与结构体用法相似)

6。共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体类型也可以出现在共用体类型定义中,数组也可以作为共用体成员。



一组数据:有老师、学生。数据包括:学号、姓名、性别、职业、班级/职务

如果职业是s第5项就是班级,如果是t第5项就是职务:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct
{
    int num;
    char name[20];
    char sex;
    char job;
    union
    {
        int classes;
        char position[20];
    }category;
}person[2];
   
main()
{
   
    int i;
   
    for(i=0;i<2;i++)
    {
        scanf("%d %s %c %c ",&person[i].num,person[i].name,&person[i].sex,&person[i].job);
        if(person[i].job=='s')
        {
            scanf("%d",&person[i].category.classes);
        }
        else if(person[i].job=='t')
        {
            scanf("%s",&person[i].category.position);
        }
        else
        {
            printf("input error!");
        }
    }
   
    printf("
");
   
    printf("No    Name      sex    Job   class/position
");
   
    for(i=0;i<2;i++)
    {
        if(person[i].job=='t')
        {
            printf("%-6d%-10s%-8c%-6c%-s
",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.position);
        }
        else
        { printf("%-6d%-10s%-8c%-6c%-d
",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.classes);
        }
    }
}


可以看出在结构体类型声明中包括了共用体类型,category是结构体成员中的一个成员名,在共用体中成员为class、position,前者为整型,后者为字符数组(存放"职务"的值--字符串).



枚举类型:

如果一个变量只有几种可能的值,可以定义为枚举类型。所谓枚举是指将变量的值一一列举出来,变量的值,只限于列举出来的值的范围内。

声明:

enum weekday(sun,mon,tue,wed,thu,fri,sat);

声明一个枚举类型enum weekday,可以用此来定义变量如:

enum weekday workday,week_end

workday和week_end被定义为枚举变量,它们的值只能是sun到sat之一。例如:

workday=mon;

week_day=sun; 

直接定义:

enum{sun,mon,tur,wed,thu,fri,sat} workday,week_end;

其中sun,mon等称为枚举常量,是用户自定义的标识符

1.枚举元素按常量处理,他们不是变量,不能对它们赋值。

2.枚举元素作为常量,他们是有值的编译按定义时的顺序使他们的值为0,1,2。。。


例:口袋中有红、黄、蓝、白、黑5种颜色球若干个。每次从口袋中取出3个球,问得到3种不同色的球可能的取法,打印出3种颜色:

#include <stdio.h>
main()
{
   
enum color{
red,yellow,blue,white,black
};
    enum color i,j,k,pri;
    int n,loop;
    n=0;
   
    for(i=red;i<=black;i++)
    {
        for(j=red;j<=black;j++)
        {
            if(i!=j)
            {
                for(k=red;k<=black;k++)
                {
                    if(k!=i&&k!=j)
                    {
                        n=n+1;
                        printf("%d: ",n);
                        for(loop=1;loop<=3;loop++)
                        {
                            switch(loop)
                            {
                                case 1:pri=i;break;
                                case 2:pri=j;break;
                                case 3:pri=k;break;
                                default:break;
                            }
   
                            switch(pri)
                            {
                                case red:printf("%s ","red");break;
                                case yellow:printf("%s  ","yellow");break;
                                case blue:printf("%s    ","blue");break;
                                case white:printf("%s   ","white");break;
                                case black:printf("%s   ","black");break;
                                default:break;
                            }
                        }
                        printf("
");
                    }
                }
            }
        }
    }
}




用typedef定义类型:

除了使用标准类型int、char、float、double、long等和自己声明的结构体、共用体、指针、枚举类型外,可以用typeof声明新的类型来代替已有的类型,如:

#include<stdio.h>
void main()
{
    typedef int INTEGER;
    typedef float REAL;
   
    int a=3;
    float b=3.45;
   
    INTEGER c = 4;
    REAL d = 4.54;
   
    printf("a:%d,c:%d
",a,c);
    printf("b:%.2f,d:%.2f
",b,d);
}


他们是等价的。

#include<stdio.h>
void main()
{
    typedef struct
    {
        int year;
        int mouth;
        int day;
    }DATE;
   
    DATE birthday; /*声明一个DATE类型的生日*/
    DATE *p /*p为指向结构体类型数据的指针*/
}


typedef int NUM[100];
NUM n;/*定义n为整型数组变量*/
typedef int *STR;/*声明STR为字符指针类型*/
STR p,s[10];/*p为字符指针变量,s为指针数组*/
typedef int  (*POINTER)();/*声明POINTER为指向函数的指针类型,函数返回整型值*/
POINTER p1,p2; /*p1,p2为POINTER类型的指针变量*/

归纳:

1.先按定义变量的方法写出定义体。

2.将变量名换成新类型名。

3.在最前面加typedef。

4.然后用新类型名定义变量。

以数组为例说明:

1.int n[100]

2.int NUM[100]

3.typefef int NUM[100]

4.NUM arr;

以字符指针说明:

1.char *p

2.char *STR

3.typedef char *STR

4.STR p,s[10];



说明:

1.用typedef可以声明各种类型名,但不能用来定义变量。

   int a[10],b[10],c[10];

   都是一堆数组大小也相同,,可将数组类型声明为一个类型

   typedef int ARR[10];

   然后用ARR去定义数组变量。

   ARR a,b,c;

2.用typedef只是对已存在的类型增加一个类型名,而没有创造新的。

   像typedef int NUM[100] 无非是把原来用int n[10]定义的数组变量类型用一个新的名字NUM表示出来。

3.typedef与#define有相似之处

   typedef int COUNT

   #define COUNT int

   作用都是用COUNT代表int,但事实上两者是不同的。

   #define 是在预编译时处理的,只能做简单的字符串替换

   typedef 是在编译时处理的,并不是做简单的字符串替换,例如:

   typedef int NUM[10] 并不是去代替int,而是如同定义变量的方法声明一个类型

4.当不同源文件中用到同一数据类型(尤其是像定义数组、指针、结构体、共用体)等类型,常用typedef声明一些数据类型,单独放在一个文件中,需要用时导包

5.使用typedef有利于程序段通用与移植

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值