C语言:构造类型(共用体/联合体,枚举)

共用体/联合体类型

定义

使几个不同的变量占用同一段内存的结构。共用体按定义中需要存储空间最大的成员来

分配存储单元,其他成员也是用该空间,他们的首地址是相同。

定义格式:

union 共用体名称
{
     数据类型 变量名;  -- 共用体成员
     数据类型 变量名;
     ...
};

公用体的定义和结构体类似:

可以有名字,也可以匿名

共用体在定义时也可以定义公用体变量

共用体在定义时也可以初始化成员

共用体也可以作为形参和返回值类型使用

共用体也可以定义共用体变量

...

也就是说,结构体的语法,共用体都支持

注意:

共用体弊大于利,尽量少用,一般很少用;

共用体变量在某一时刻只能存一个数据,并且也只能取出一个数

共用体和结构体都是自定义数据类型,用法类似于基本数据类型

共用体可以是共用体的成员,也可以是结构体的成员

结构体可以是结构体的成员,也可以是共用体的成员

案例:

/**
 * 共用体
 */
#include <stdio.h>
// 定义共用体
union S
{
    char a;
    float b;
    int c;
};// 大小是4字节
// 共用体作为共用体的成员
union F
{
    char a;
    union S s; // 4字节
};// 大小是4字节
// 共用体作为结构体的成员
struct G
{
    int a;
    union S s;
};// 大小是8字节
// 定义一个结构体
struct H
{
    int a;
    char b;
};// 大小是8字节
// 结构体作为结构体成员
struct I
{
    int a; // 4
    int b; // 4
    struct H h; // 8
};// 大小是16字节
// 共用体作为结构体成员
struct J
{
    int a;// 4
    char b;// 1 + 3
    union S s;// 4
};// 大小是12字节
void test1()
{
// 定义共用体类型
    union Stu
   {
        int num;
        char sex;
        double score;
   };
    // 定义匿名共用体:匿名共用体一般作为结构体成员或者其他共用体成员
    union
   {
        int a;
        char c;
   } c;
    printf("%lu,%lu\n",sizeof(union Stu),sizeof(c));
}
void test2()
{
    union C
   {
        int a;
        char b;
   };
    
    // 定义变量
    union C c; 
    // 存数据
    c.a = 10;
    c.b = 'A';
    printf("%d---%d\n",c.a,c.b);// 取数据
    c.a += 5;
    printf("%d---%d\n",c.a,c.b);// 取数据
    union E
   {
        char *f;
        long a;
        int b;
   } e = {"hello world!"};
    printf("%s,%p---%ld,%p---%d\n",e.f,&(e.f),e.a,&(e.a),e.b);
}
int main()
{
    test1();
    test2();
}

枚举类型

定义

我们一般情况下,定义常量使用宏定义(#define 红名称值),宏定义非常适合没有关联关系的

常量;但是有时候我们可能需要对一组拥有关联关系的量进行定义,比如 ==周一~周日、1月~12

月、方向(上下左右中)等 ,那么使用宏定义,就不是很清晰,这个时候就需要使用到枚举。

枚举的存在就是将多个拥有关系的常量组合到一起,提高代码的可读性。

说明:

枚举类型定义了一组常量,我们在开发中直接使用这些常量。(常用)

当然枚举类型也可以类似于结构体一样定义变量等操作。(不常用)

枚举常量有默认值,从0开始依次+1;我们可以在定义时指定它的默认值,如果个别没有赋值,

可以根据赋值依次+1推导。

特点:

定义了一组常量,类似于定义了多个自定义常量(宏定义)

提供了代码的可读性。

定义语法:

定义枚举类型名以后就可以定义该枚举类型的变量。

enum 枚举类型名 变量列表;

在定义枚举类型的同时定义该枚举类型的变量。

enum 枚举类型名{枚举元素列表} 变量列表;

直接定义枚举变量

enum {枚举元素列表} 变量列表;

案例:

#include <stdio.h>
void test1()
{
 // 定义一个枚举类型
    // 枚举类型名一般首字母大写,主要是根枚举变量区分
    enum Week 
   {
       // 定义枚举元素,元素命名要符合标识符命名规则,同时采用大写字母+下划线方式命名
       SUN=10,MON,TUE,WED,THU,FRI,SAT
   };
    // 1.直接访问枚举元素
    printf("%d,%d,%d\n",SUN,WED,SAT);
    // 2.定义枚举类型的变量(先定义变量,后赋值)
    enum Week week;
    // 初始化
    week = TUE;// 一定是这个枚举类型中定义的元素
    printf("%d\n",week);
    // 3.定义枚举类型变量的同时赋值(定义变量和赋值同时进行)
    enum Week week1 = THU;
    printf("%d\n",week1);
    enum H
   {
        A,B,C // 多个元素使用逗号分隔
} x,y;
    x = B;
    y = C;
    printf("x=%d,y=%d\n",x,y);// 1,2
}
void test2()
{
 // 定义枚举
 enum CaiQuan
 {
 SHI_TOU,JIAN_DAO,BU
 };
 printf("请输入0~2之间的整数:\n[0-石头,1-剪刀,2-布]\n");
 int number;
 scanf("%d",&number);
 switch(number)
 {
 case SHI_TOU:
    printf("石头\n");
    break;
 case JIAN_DAO:
    printf("剪刀\n");
    break;
 case BU:
    printf("布\n");
    break;
 }
}
int main(int argc,char *argv[])
{
    test1();
 test2();
    return 0;
}

typedef

说明:给类型重命名,不会影响到类型本身

作用:给已有的类型起别名

格式:

typedef 已有类型名 新别名;

使用:

// 方式1:先定义结构体类型,再重命名
// 定义一个结构体类型
struct Student
{
    int id;
    char *name;
    char sex;
    int age;
};
// 类型重命名
typedef struct Student Stu;
// 定义结构体变量
struct Stu stu = {1,"张三",'w',21};
// 方式2:定义结构体的同时重命名
typedef struct PersonInfo
{
    int a;
    double b;
} Per; // 结构体类型的别名,本质上还是数据类型
// 定义变量
struct Per per = {2,5};

应用场景:

数据类型复杂(结构体、共用体、枚举、结构体指针、无符号的长整型)时使用

为了跨平台兼容性,例如:

  1. size_t:类型重命名后的数据类型: typedef unsigned long size_t;

  2. unit_16:类型重命名后数据类型

案例:

//类型重命名
#include <stdio.h>
struct Student
{
    int age;
    char* name;
    double score;
    int arr[3];
};
typedef struct Student  Stu_t;// 数据类型重命名
typedef Stu_t* pStu_t;// 结构体指针重命名
void test1()
{
    Stu_t s1 = {23, "zhangsan", 23.33, {11, 22, 33}};
    printf("%d, %s, %f, %d\n", s1.age, s1.name, s1.score, s1.arr[0]);
    
    //Stu_t *p = &s1;
    Stu_t*  p;
    p = &s1;
    pStu_t p2;
    p2 = p;
    printf("%d, %s, %f, %d\n", p2->age, p2->name, p2->score, p2->arr[0]);
    
}
int main()
{
    test1();
    return 0;
}
相关推荐
longze_728 分钟前
国产信创实践(国能磐石服务器操作系统CEOS +东方通TongHttpServer)
linux·服务器·nginx·ubuntu·centos·操作系统·openeuler
Paper_Love34 分钟前
Linux-蓝牙协议
linux
JoneMaster1 小时前
[读书日志]从零开始学习Chisel 第十一篇:Scala的类型参数化(敏捷硬件开发语言Chisel与数字系统设计)
开发语言·学习·scala
一决威严-雪雪1 小时前
springboot整合admin
java·spring boot·后端
吴秋霖1 小时前
某漫画网站JS逆向反混淆流程分析
开发语言·javascript·ecmascript
栗筝i1 小时前
Spring 中的常用注解
java·后端·spring
Growthofnotes1 小时前
C++—14、C++ 中的指针最基础的原理
开发语言·c++
OopspoO1 小时前
Linux内核学习——数据结构
linux·数据结构
大时代11051 小时前
NAT && 代理服务器
linux
小登ai学习1 小时前
框架部分面试题学习
java·学习·面试